设置 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)
我正在将我的应用程序升级到 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)