NSPersistentStoreCoordinator throws EXC_BAD_ACCESS when deallocating an NSManagedObject after reading a specific NSManagedProperty

假装没事ソ 提交于 2019-12-12 20:03:16

问题


Error Description

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:


What I've Tried So Far

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.

Edit

Not sure if this will help, but here's my model schema


回答1:


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.



来源:https://stackoverflow.com/questions/40687218/nspersistentstorecoordinator-throws-exc-bad-access-when-deallocating-an-nsmanage

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!