2

总结一下我所做的:

  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。此外,我还根据官方文档将实体的类更新为2048.BestScoreModel 。

  5. 在控制器类中,我添加了以下变量

    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:我从这里得到托管对象上下文的实现。非常感谢作者!

4

2 回答 2

2

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

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

Swift 托管对象子类(Xcode 还不能自动创建)看起来像这样:

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

我使用了NSNumbertype 而不是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!

此外,如果应用程序第二次运行,您可能希望重新加载现有的最佳分数,而不是创建新对象。这意味着您必须先执行一个 fetch 请求,并且只有在没有找到新对象时才插入一个新对象:

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
于 2014-07-13T09:35:23.153 回答
0

尝试为.xcdatamodeld文件中的实体指定模块名称。有关详细说明,请参阅“Using Swift with Cocoa and Objective-C (Swift 2.1)”一书中的实现核心数据托管对象子类部分,如果您能找到它。

于 2016-02-01T20:26:32.927 回答