DrWhat DrWhat - 6 months ago 27
iOS Question

Variable instantiated in prepare for Segue has nil properties in ViewDidLoad

My view controller is loading before Core Location data is available from the model.

I've a Master View controller that modally pushes a new view controller with two

NSManagedObject
subclasses - records and locations - which are instantiated in a
prepareForSegue
method.

if segue.identifier == "newRecord"
{
let controller = (segue.destinationViewController as! NewRecordVC)

let appDelegate = UIApplication.sharedApplication().delegate as? AppDelegate // instantiate the delegate methods in AppDelegate

let managedContext = appDelegate!.managedObjectContext // create context from delegate methods

let recordEntity = NSEntityDescription.entityForName("RecordData", inManagedObjectContext: managedContext)
let locationEntity = NSEntityDescription.entityForName("Location", inManagedObjectContext: managedContext)

controller.location = Location(entity: locationEntity!, insertIntoManagedObjectContext: managedContext)
controller.record = Record(entity: recordEntity!, insertIntoManagedObjectContext: managedContext)
controller.managedContext = appDelegate?.managedObjectContext
print("segueing")
}


Both managed objects have
inits
for various values. Records have simple pre-assigned values assigned to properties that show up on the new view. Location properties, however, mainly require location services to assign property values. Printing property values shows that while a location is instantiated in
viewDidLoad
, the location properties assigned by location services are still nil. Location services are working - the properties print from within the model, BUT this is after
viewDidLoad
. On load, I need at least the
geoPlacemark
property, which provides text for the view.

override func viewDidLoad()
{
super.viewDidLoad()
...
if let recordNotNil = record
{
...
iD.text = "ID: \(recordNotNil.iD)"
}

if let locationNotNil = location
{
...
print("bing")
print(locationNotNil.temp)
record!.location = location!
print(location.geoPlacemark)
print(location.timestamp)
if let geoPlacemarkNotNil = location.geoPlacemark
{
print("bong")
locationText(geoPlacemarkNotNil)
}
}
}


Do I have to run the location services from within every view controller, not the model? Or is there a way to get the view to wait for the location delegate methods?

Answer

The problem here came from using the normal override init method for the NSManagedObject.

class Record: NSManagedObject
{
override init(entity: NSEntityDescription, insertIntoManagedObjectContext context: NSManagedObjectContext?)
{
    super.init(entity: entity, insertIntoManagedObjectContext: context)
    let randomBit = String(arc4random_uniform(100))
    iD = NSDate().toIDTimeDateString() + "-" + randomBit + "OtR"

    believers = 0
    deviceTime = NSDate()
    doubters = 0
    eventTimeStarted = NSDate()
    eventTimeEnded = NSDate()
    featureImageIndex = 0
    coreLocationUsed = 0
    photoTaken = 0
    tableSection = "My Records"
    timeRecorded = deviceTime
    validationScore = 0
}
}

As per the apple doc.s, custom NSManagedObjects should be initiated using awakeFromInsert or awakeFromFetch.

Comments