I have an app with some data stored locally using core data (backed by SQLite) and the following NSManagedObject
subclass
import CoreData
@objc(ScoutingEventData)
class ScoutingEventData: NSManagedObject {
@NSManaged var id: String?
@NSManaged var type: String?
@NSManaged var entityId: String?
@NSManaged var oldStateJson: NSData?
@NSManaged var newStateJson: NSData?
@NSManaged var eventDate: NSDate?
func toInsertEvent() throws -> ScoutingEvent.Insert {
guard let id = id else { fatalError("events should have an event id") }
guard let data = newStateJson else { fatalError("insert event should have newStateJson stored") }
// If I uncomment this line, the error goes away.
// Somehow by ensuring that data never gets deallocated, the error never occurs.
// globallllll = data
return ScoutingEvent.Insert(id: id, entity: try ScoutingEntity.from(data))
}
}
// debugging var to prevent data from being deallocated
var globallllll: NSData?
As mentioned in the comment in the snippet above, there is an error occurring if I allow the value I read out of the newStateJson
property to be deallocated.
The error I receive comes from a background thread:
If I enable zombies in the diagnostic tool, I get this instead
And I also get the following message in the console if zombies are enabled:
2016-11-18 16:26:13.773 ScoutingData_Example[51750:4716636] *** -[CFData release]: message sent to deallocated instance 0x7f8c4eb10ae0
And the following stack trace:
I have tried storing the NSManagedObjectContext
which was used to fetch this data in a static variable to ensure that the context never gets deallocated, but that had no effect.
I have tried converting the NSData?
properties to String?
properties, and storing the data as a Base64 encoded string instead of binary data (and also updating the backing model), but that had no effect either. The error still persisted.
I have tried commenting out the code that reads the property, and the error dissappeared, but that is obviously not an acceptable solution.
I have tried storing the value in a global variable after reading it, to prevent it from ever being deallocated, and the error dissappeared, but that is also not a valid solution.
I have tried commenting out all the code that uses the value, and instead only printing the value to the console, and the error persisted. This leads me to believe that the act of accessing the property at all, and then deallocating it later, is what creates the conditions for this error.
I am pretty stumped. It seems really odd that it should matter what I do with the data after I read it, and it seems especially odd that anything happens on a background thread when it gets deallocated.
What's even more odd is that it seems specific to this one property. For instance, the id property which I read right above the line that reads the newDataJson property doesn't cause any problems. You might think thats different because the id is a string, not NSData, but I tried converting my NSData property to a string property instead, and it still didn't change the error.
Any ideas would be greatly appreciated. Thanks.
Not sure if this will help, but here's my model schema
Give the property a name that doesn't start with new
. I have had similar problems and had to rename my property to something like theNewState
. I think the new
prefix has special meaning and confuses ARC memory management.
Edit: reference Apple ARC release notes, see the section saying "You cannot give an accessor a name that begins with new." So it's actually the accessor/getter name, not the property name itself.