【问题标题】:NSPersistentStoreCoordinator throws EXC_BAD_ACCESS when deallocating an NSManagedObject after reading a specific NSManagedPropertyNSPersistentStoreCoordinator 在读取特定 NSManagedProperty 后释放 NSManagedObject 时抛出 EXC_BAD_ACCESS
【发布时间】:2016-11-18 22:58:57
【问题描述】:

错误说明

我有一个应用程序,其中一些数据使用核心数据(由 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?

如上面 sn-p 中的评论所述,如果我允许释放从 newStateJson 属性中读取的值,则会发生错误。

我收到的错误来自后台线程:

如果我在诊断工具中启用僵尸,我会得到这个

如果启用了僵尸,我还会在控制台中收到以下消息:

2016-11-18 16:26:13.773 ScoutingData_Example[51750:4716636] *** -[CFData release]:消息发送到释放的实例 0x7f8c4eb10ae0

还有以下堆栈跟踪:


到目前为止我已经尝试过什么

我已尝试将用于获取此数据的 NSManagedObjectContext 存储在静态变量中,以确保上下文永远不会被释放,但这没有任何效果。

我尝试将NSData? 属性转换为String? 属性,并将数据存储为Base64 编码字符串而不是二进制数据(并且还更新了支持模型),但这也没有效果。错误仍然存​​在。

我尝试注释掉读取属性的代码,错误消失了,但这显然不是一个可接受的解决方案。

我尝试在读取后将值存储在全局变量中,以防止它被释放,并且错误消失了,但这也不是一个有效的解决方案。

我尝试注释掉所有使用该值的代码,而只将值打印到控制台,错误仍然存​​在。这让我相信完全访问该属性,然后再释放它的行为是造成此错误的条件。


我很困惑。读取数据后如何处理数据似乎很奇怪,而且当后台线程被释放时发生任何事情似乎特别奇怪。

更奇怪的是,它似乎特定于这一属性。例如,我在读取 newDataJson 属性的行上方读取的 id 属性不会导致任何问题。您可能会认为这不同,因为 id 是字符串,而不是 NSData,但我尝试将我的 NSData 属性转换为字符串属性,但它仍然没有改变错误。

任何想法将不胜感激。谢谢。

编辑

不确定这是否会有所帮助,但这是我的模型架构

【问题讨论】:

    标签: ios swift core-data nsmanagedobject nspersistentstore


    【解决方案1】:

    为属性指定一个不以new 开头的名称。我遇到了类似的问题,不得不将我的属性重命名为theNewState。我认为new前缀有特殊含义,会混淆ARC内存管理。

    编辑:参考Apple ARC release notes,参见“你不能给访问者一个以新开头的名字”的部分。所以它实际上是访问器/获取器名称,而不是属性名称本身。

    【讨论】:

    • 这太神奇了,也太荒谬了。非常感谢。我无法想象遇到这种情况需要多长时间
    猜你喜欢
    • 1970-01-01
    • 2012-01-21
    • 2019-01-25
    • 1970-01-01
    • 2011-01-08
    • 2010-10-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多