core-data - ManagedObjectModel 子类在 Swift 中不起作用

标签 core-data swift nsmanagedobject nsmanagedobjectmodel

总结一下我所做的事情:

  1. 创建了一个名为 2048 的项目。

  2. 创建了 NSManagedObject 的子类

    class BestScore: NSManagedObject {
        @NSManaged var bestScoreModel: BestScoreModel
        func update(score: Int) {
            self.bestScoreModel!.score = score
        }
    }
    
  3. 创建了 NSManagedObjectModel 的子类

    class BestScoreModel: NSManagedObjectModel {
        @NSManaged var score: Int
    }
    
  4. 在“核心数据”选项卡下创建了一个数据模型。将该文件命名为 2048.xcdatamodeld。添加了一个实体BestScoreModel,其属性为“score”,并将类型定义为Integer 16。此外,我还根据official document将实体的类更新为2048.BestScoreModel。 .

  5. 在 Controller 类中,我添加了以下变量

    class HomeViewController: UIViewController {
    
        var bestScore: BestScore?
    
        @lazy var context: NSManagedObjectContext = {
            let serviceName = NSBundle.mainBundle().infoDictionary.objectForKey("CFBundleName") as String
            let modelURL = NSBundle.mainBundle().URLForResource(serviceName, withExtension: "momd")
            let model = NSManagedObjectModel(contentsOfURL: modelURL)
            if model == nil {
                println("Error initilizing model from : \(modelURL)")
                abort()
            }
            let coordinator = NSPersistentStoreCoordinator(managedObjectModel: model)
            let urls = NSFileManager.defaultManager().URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask)
            let storeURL = (urls[urls.endIndex-1]).URLByAppendingPathComponent("\(serviceName).sqlite")
            var error: NSError? = nil
            var store = coordinator.addPersistentStoreWithType(NSSQLiteStoreType, configuration: nil, URL: storeURL, options: nil, error: &error)
            if store == nil {
                println("Failed to load store at \(storeURL) with error: \(error?.localizedDescription)")
                abort()
            }
            var context = NSManagedObjectContext()
            context.persistentStoreCoordinator = coordinator
            return context
        }()
    
        override func viewDidLoad() {
            super.viewDidLoad()
            let entity: NSEntityDescription = NSEntityDescription.entityForName("BestScoreModel", inManagedObjectContext: context)
            bestScore = BestScore(entity: entity, insertIntoManagedObjectContext: context)
            bestScore.update(0)
        }
    }
    

应用程序已成功构建,但当我运行模拟器时,它抛出以下异常

    2014-07-13 00:56:59.944 2048[76600:4447122] -[NSManagedObject update:]: unrecognized selector sent to instance 0x10bc55d20
    2014-07-13 00:56:59.948 2048[76600:4447122] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[NSManagedObject update:]: unrecognized selector sent to instance 0x10bc55d20'

我对 iOS 开发完全陌生,之前没有任何经验。我想以 Swift 为契机,在不学习 Objective-C 的情况下开始编写应用程序。如果我配置错误,请告诉我。

感谢您的帮助。

PS:我从 here 获取托管对象上下文的实现。非常感谢作者!

最佳答案

NSManagedObjectModel 描述了应用程序中使用的所有实体的集合,通常没有理由对其进行子类化。

我建议您对实体和相应的实体使用相同的名称 管理对象的子类。 (这也是 Xcode 在创建 Objective-C 托管对象子类时所做的事情)

Swift 托管对象子类(Xcode 尚无法自动创建) 看起来就像这样:

class BestScore: NSManagedObject {
    @NSManaged var score: NSNumber
}

我使用了 NSNumber 类型而不是 Int16,因为 Swift 中的标量访问器方法是托管的 对象子类尚未正常工作,比较 How to use Core Data Integer 64 with Swift Int64? .

然后将创建一个新的 BestScore 对象

bestScore = NSEntityDescription.insertNewObjectForEntityForName("BestScore", inManagedObjectContext: context) as BestScore

您可以直接访问其属性,而不需要 update() 函数:

bestScore!.score = 0

其他备注:bestScore 属性定义为 隐式解包可选,因为您希望它在之后有一个值 viewDidLoad:。这可以节省您以后的许多显式展开操作:

var bestScore: BestScore!

此外,如果应用程序第二次运行,您可能需要重新加载 现有的最佳分数,而不是创建一个新的对象。 这意味着您必须先执行获取请求,然后插入新的 仅当未找到时才对象:

let request = NSFetchRequest(entityName: "BestScore")
var error : NSError?
let result = context.executeFetchRequest(request, error: &error)

if !result || result.count == 0 {
    // Error or no object found: create new one:
    bestScore = NSEntityDescription.insertNewObjectForEntityForName("BestScore", inManagedObjectContext: context) as BestScore
    bestScore.score = 0
} else {
    // Use existing object:
    bestScore = result[0] as BestScore
}
let score = bestScore.score.integerValue // NSNumber --> Integer

关于core-data - ManagedObjectModel 子类在 Swift 中不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24720855/

相关文章:

ios - 子类化 NSManagedObject 子类

ios - 将 NSManagedObject 变成部分错误,其中某些字段为零,有些字段不是

cocoa-touch - 间接使用 NSManagedObject 时发送到已释放实例的消息

ios - 核心数据, "sorting by transient property"解决方法

iphone - ios Kill 应用程序问题

ios - 点击区域时不显示本地通知

ios - ViewContainer 中 ViewController 上的条形按钮操作

ios - 滚动时大标题 UINavigationbar 底线闪烁

swift - 将 CoreData 存储在 iCloud 中

iphone - 添加要存储的新对象时核心数据关系丢失