ios - 使用 nil 必需属性保存上下文时,Core Data 自定义访问器崩溃

标签 ios swift core-data magicalrecord

看完this excellent article关于 Swift 中的自定义访问器,我从 NSDecimalNumber 重构为使用新的 Decimal 类型。我有一个相当复杂的模型,几天来一切正常,但如果我在必需(非可选)属性为 nil 时保存托管对象上下文,我现在看到 EXC_BAD_ACCESS 崩溃,baseAmount 在我的例子中。直接使用NSDecimalNumber时,在重构之前,保存对象会失败,但不会崩溃。

不确定这是否重要,但我正在使用 Magical Record 的函数保存上下文:NSManagedObjectContext.mr_default().mr_saveToPersistentStoreAndWait()

关于如何修改 baseAmount 访问器以实现与 Core Data 提供的相同的失败保存行为以使其不会崩溃,有什么想法吗?

这是我的 NSManagedObject 子类的相关部分,后面是堆栈跟踪:

extension DFTransaction {

    @NSManaged private var primitiveBaseAmount: NSDecimalNumber

    var baseAmount: Decimal {
        get {
            willAccessValue(forKey: "baseAmount")
            defer { didAccessValue(forKey: "baseAmount") }
            return primitiveBaseAmount.decimalValue
        }
        set {
            willChangeValue(forKey: "baseAmount")
            defer { didChangeValue(forKey: "baseAmount") }
            primitiveBaseAmount = NSDecimalNumber(decimal: newValue)
        }
    }
}


[appname]`@objc DFTransaction.baseAmount.getter:
0x100343cd0 <+0>:   stp    x29, x30, [sp, #-16]!
0x100343cd4 <+4>:   mov    x29, sp
0x100343cd8 <+8>:   sub    sp, sp, #96               ; =96 
0x100343cdc <+12>:  stur   x0, [x29, #-32]
0x100343ce0 <+16>:  stur   x8, [x29, #-40]
0x100343ce4 <+20>:  bl     0x10051ca64               ; symbol stub for: objc_retain
0x100343ce8 <+24>:  sub    x8, x29, #24              ; =24 
0x100343cec <+28>:  ldur   x30, [x29, #-32]
0x100343cf0 <+32>:  str    x0, [sp, #48]
0x100343cf4 <+36>:  mov    x0, x30
0x100343cf8 <+40>:  bl     0x100343da4               ; [appname].DFTransaction.baseAmount.getter : __C.Decimal at DFTransaction.swift:64
0x100343cfc <+44>:  ldur   w9, [x29, #-24]
0x100343d00 <+48>:  ldurh  w10, [x29, #-20]
0x100343d04 <+52>:  ldurh  w11, [x29, #-18]
0x100343d08 <+56>:  ldurh  w12, [x29, #-16]
0x100343d0c <+60>:  ldurh  w13, [x29, #-14]
0x100343d10 <+64>:  ldurh  w14, [x29, #-12]
0x100343d14 <+68>:  ldurh  w15, [x29, #-10]
0x100343d18 <+72>:  ldurh  w16, [x29, #-8]
0x100343d1c <+76>:  ldurh  w17, [x29, #-6]
0x100343d20 <+80>:  ldur   x0, [x29, #-32]
0x100343d24 <+84>:  str    w9, [sp, #44]
0x100343d28 <+88>:  str    w10, [sp, #40]
0x100343d2c <+92>:  str    w11, [sp, #36]
0x100343d30 <+96>:  str    w12, [sp, #32]
0x100343d34 <+100>: str    w13, [sp, #28]
0x100343d38 <+104>: str    w14, [sp, #24]
0x100343d3c <+108>: str    w15, [sp, #20]
0x100343d40 <+112>: str    w16, [sp, #16]
0x100343d44 <+116>: str    w17, [sp, #12]
0x100343d48 <+120>: bl     0x10051ca58               ; symbol stub for: objc_release
0x100343d4c <+124>: ldr    w9, [sp, #44]
0x100343d50 <+128>: ldur   x8, [x29, #-40]
->  0x100343d54 <+132>: str    w9, [x8]    //EXC_BAD_ACCESS
0x100343d58 <+136>: ldr    w10, [sp, #40]
0x100343d5c <+140>: strh   w10, [x8, #4]
0x100343d60 <+144>: ldr    w11, [sp, #36]
0x100343d64 <+148>: strh   w11, [x8, #6]
0x100343d68 <+152>: ldr    w12, [sp, #32]
0x100343d6c <+156>: strh   w12, [x8, #8]
0x100343d70 <+160>: ldr    w13, [sp, #28]
0x100343d74 <+164>: strh   w13, [x8, #10]
0x100343d78 <+168>: ldr    w14, [sp, #24]
0x100343d7c <+172>: strh   w14, [x8, #12]
0x100343d80 <+176>: ldr    w15, [sp, #20]
0x100343d84 <+180>: strh   w15, [x8, #14]
0x100343d88 <+184>: ldr    w16, [sp, #16]
0x100343d8c <+188>: strh   w16, [x8, #16]
0x100343d90 <+192>: ldr    w17, [sp, #12]
0x100343d94 <+196>: strh   w17, [x8, #18]
0x100343d98 <+200>: mov    sp, x29
0x100343d9c <+204>: ldp    x29, x30, [sp], #16
0x100343da0 <+208>: ret    

最佳答案

在文章中我提到“原始访问器总是可为空的 Objective-C 引用类型”。这是一个不受 isOptional 设置影响的事实,正如您在这些崩溃中所发现的那样。

因此,原始访问器必须这样声明:

@NSManaged 私有(private)变量 primitiveBaseAmount: NSDecimalNumber?

除此之外,您已将 baseAmount 访问器声明为 Decimal(非可选),因此您的自定义 get 实现必须执行一些非当它遇到一个 null 原始值时会崩溃,比如 return primitiveBaseAmount?.decimalValue ?? 0

关于ios - 使用 nil 必需属性保存上下文时,Core Data 自定义访问器崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39518655/

相关文章:

ios - 如何将数组对象转换为 JSON 字符串。苹果8. swift 1.2

ios - 照片和视频未保存在我的自定义相册中

ios - 在 StoryBoard TabBar 上设置托管对象上下文 - 具有嵌入式导航 Controller 的 TableView Controller

ios - 从 Facebook 页面获取事件

ios - UIWebView 不显示任何内容

ios - 每天在 Swift 中重置 NSUserDefault key

xcode - 工具栏未锁定到屏幕底部,Xcode

iOS - 使用动画展开/折叠 UITableView 部分

swift - 保存在后台线程后,多线程核心数据对象在主线程上具有空属性

objective-c - 删除核心数据实体