我有一个应用程序,其中一些数据存储在本地使用核心数据(由SQLite支持)和以下NSManagedObject
子类
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?
如上面代码段中的注释所述,如果我允许释放newStateJson
属性中读取的值,则会发生错误。
我收到的错误来自后台主题:
如果我在诊断工具中启用僵尸,我会改为
如果启用了僵尸,我还会在控制台中收到以下消息:
2016-11-18 16:26:13.773 ScoutingData_Example [51750:4716636] *** - [CFData发布]:发送到解除分配的实例0x7f8c4eb10ae0的消息
以下堆栈跟踪:
我已经尝试存储用于在静态变量中获取此数据的NSManagedObjectContext
,以确保上下文永远不会被释放,但是没有效果。
我尝试将NSData?
属性转换为String?
属性,并将数据存储为Base64编码的字符串而不是二进制数据(并且还更新了支持模型),但这也没有影响。该错误仍然存在。
我试过注释掉读取属性的代码,但错误消失了,但这显然不是一个可接受的解决方案。
我已经尝试在读取后将值存储在全局变量中,以防止它被解除分配,并且错误消失了,但这也不是有效的解决方案。
我已经尝试注释掉使用值的所有代码,而只是将值打印到控制台,并且错误仍然存在。这使我相信完全访问该属性的行为,然后在以后解除分配,就是造成此错误的条件。
我很难过。在我阅读之后,我对数据的处理方式似乎很奇怪,并且当它被解除分配时,后台线程上发生的任何事情似乎都很奇怪。
更奇怪的是,它似乎特定于这一个属性。例如,我在读取newDataJson属性的行上方读取的id属性不会导致任何问题。你可能会认为这是不同的,因为id是一个字符串,而不是NSData,但我尝试将我的NSData属性转换为字符串属性,但它仍然没有改变错误。
任何想法都将不胜感激。感谢。
不确定这是否有帮助,但这是我的模型架构
答案 0 :(得分:4)
为属性指定一个不以new
开头的名称。我遇到过类似的问题,不得不将我的财产重命名为theNewState
。我认为new
前缀具有特殊含义并且会混淆ARC内存管理。
编辑:引用Apple ARC release notes,请参阅“您无法为访问者提供以新名称开头的名称”部分。所以它实际上是访问者/获取者名称,而不是属性名称本身。