设置 NSManagedObject 的 Bool 属性会引发 "Uncaught exception in iOS 10"

Setting Bool attribute of an NSManagedObject throws "Uncaught exception in iOS 10"

我正在将我的应用程序升级到 iOS 10 / swift 3

所以用字典(从远程数据库接收的值)以这种方式构建 NSManagedObject...

    let writerDictionary = [
        ...: writer.id,
        ...: writer.name,
        ...: writer.picture,
        ...: writer.publicationID,
        ...: writer.language,
        ...: writer.country
    ]

    let newWriter = Writer(dictionary: writerDictionary, context: SHARED_CONTEXT)

isFavorite 是一个 NSManaged 属性,我在保存前构造 newWriter 对象后立即用 newWriter.isFavorite = true 手动设置为 true上下文 -

此行因 iOS 10 中的未捕获异常而崩溃 - 以前 iOS 9

没有任何问题

我也试过 newWriter.setValue(true, forKey: "isFavorite") - 虽然它不会使应用程序崩溃,但 bool 值 isFavorite 保持 false 不变。

有什么想法吗?这是我的 NSManagedObject

的 Writer 子类
import UIKit
import CoreData

@objc(Writer)

class Writer: NSManagedObject {

    // Attributes also in the database
    @NSManaged var id: NSNumber
    @NSManaged var name: String
    @NSManaged var picture: String?
    @NSManaged var publicationID: NSNumber
    @NSManaged var language: String
    @NSManaged var country: String
    @NSManaged var lastArticle: Date

    // Attributes only in the iOS app
    @NSManaged var isFavorite: Bool           // Initial value is false
    @NSManaged var hasNewArticles: Bool

    // Relationship objects
    @NSManaged var publication: Publication
    @NSManaged var articles: [Article]

    var writerImage: UIImage? {
        get {
            return ImageCache.sharedCache.imageWithIdentifier("writers-" + String(id))
        }
        set {
            ImageCache.sharedCache.storeImage(newValue, withIdentifier: "writers-" + String(id))
        }
    }

    override init(entity: NSEntityDescription, insertInto context: NSManagedObjectContext?) {
        super.init(entity: entity, insertInto: context)
    }

    init(dictionary: [String : AnyObject], context: NSManagedObjectContext) {
        let entity = NSEntityDescription.entity(forEntityName: "Writer", in: context)!
        super.init(entity: entity, insertInto: context)

        id = ...  
        name = ...  
        picture = ...  
        publicationID = ...  
        language = ...  
        country = ...  
        lastArticle = ...  
    }

    override func prepareForDeletion() {
        if let _ = writerImage {
            writerImage = nil
        }
    }
}

解决方案

当前版本的 Swift 3 beta 似乎在处理以 "is" 为前缀的属性方面存在一些缺陷。

像这样调整属性的名字,解决了...

 @NSManaged @objc(isFavorite) var isFavorite: Bool

已在 Xcode 8 beta 3 编译器中修复。

来自发行说明:

Earlier Swift 3 betas implicitly renamed the property, getter, and setter for @objc properties of type Bool whose names started with “is”, to match the Objective-C naming conventions. (For example, a Swift boolean property named isMagical generated an Objective-C declaration of the form @property (nonatomic, getter=isMagical) BOOL magical.) This turned out to cause more trouble than it was worth and has been removed. (26847223)