RestKit,CoreData和Swift – 我似乎无法取回结果

我已经在一个新的基于Swift的应用程序(目前是XCode 6 beta 3)中成功设置了RestKit到CoreData的映射实现。 我知道导入映射正在使用我的RestKit JSON调用,因为我可以检查sqlite数据库并查看我的数据。 但是,我无法在NSFetchRequest中将数据从数据存储中取出。 我究竟做错了什么?

我将保留所有RestKit设置和拆卸,因为它非常标准,看起来效果很好。 所以这是我的AppDelegate查询代码似乎不起作用:

var currentUser: User? { if !_currentUser { var error: NSError? = nil let request = NSFetchRequest(entityName: "User") let recordCount = self.managedObjectContext.countForFetchRequest(request, error:&error) NSLog("user records found: \(recordCount)") var result = self.managedObjectContext.executeFetchRequest(request, error:&error) for resultItem : AnyObject in result { _currentUser = resultItem as? User if _currentUser { NSLog("Fetched User for \(_currentUser!.firstname) \(_currentUser!.lastname)") } } } return _currentUser; } 

self.managedObjectContext从我的AppDelegate引用它来从RestKit shareObject获取上下文:

 var managedObjectContext: NSManagedObjectContext { return RKObjectManager.sharedManager().managedObjectStore.mainQueueManagedObjectContext } 

似乎提取请求成功,因为for / in循环中出现断点。 但是,当我检查resultItem或_currentUser对象时,它们显示为空,并且“if _currentUser”NSLog永远不会触发。

有任何想法吗? 我是否对在Swift中恢复数据做出了错误的假设?

编辑2:

问题源于我尝试将resultItem置于Optional中。 如果声明_currentUser没有可选项并删除as? 可选的强制转换查询返回一个合适的User对象:

  for resultItem : AnyObject in result { _currentUser = resultItem as User NSLog("Fetched User for \(_currentUser.firstname) \(_currentUser.lastname)") } 

编辑:我在主要获取请求之前添加了一个记录计数,它正确地显示了1条记录。 因此,我试图将获取结果映射到我的用户对象的方式出了问题。 这是我的用户类:

 import Foundation import CoreData class User: NSManagedObject { @NSManaged var id: Int32 @NSManaged var createdAt: NSDate @NSManaged var udpatedAt: NSDate @NSManaged var username: String @NSManaged var email: String @NSManaged var firstname: String @NSManaged var lastname: String @NSManaged var organization: String @NSManaged var tokens: NSArray } 

答案是,显然Swift不喜欢将获取结果作为可选项进行转换。 我必须将结果放入局部变量然后设置可选:

 var currentUser: User? { if !_currentUser { var error: NSError? = nil let request = NSFetchRequest(entityName: "User") let recordCount = self.managedObjectContext.countForFetchRequest(request, error:&error) NSLog("user records found: \(recordCount)") var result = self.managedObjectContext.executeFetchRequest(request, error:&error) for resultItem : AnyObject in result { var currentUserItem = resultItem as User NSLog("Fetched User for \(currentUserItem.firstname) \(currentUserItem.lastname)") _currentUser = currentUserItem } } return _currentUser; } 

这是我在Swift中设置和拆解RestKit,以防任何人(如niiamon)发现它有用:

来自我的RestApi.swift:

 var objectStore: RKManagedObjectStore = RKManagedObjectStore() init() { configureRestKit() } func configureRestKit() { let objectManager = RKObjectManager(baseURL: NSURL.URLWithString(baseUrl)) //objectManager.requestSerializationMIMEType = RKMIMETypeJSON; RKObjectManager.setSharedManager(objectManager) objectStore = RKManagedObjectStore(managedObjectModel: managedObjectModel()) let dataPath = "\(RKApplicationDataDirectory())/MyApp.sqlite" NSLog("Setting up store at \(dataPath)") objectStore.addSQLitePersistentStoreAtPath(dataPath, fromSeedDatabaseAtPath: nil, withConfiguration: nil, options: optionsForSqliteStore(), error: nil) objectStore.createManagedObjectContexts() objectStore.managedObjectCache = RKInMemoryManagedObjectCache(managedObjectContext: objectStore.persistentStoreManagedObjectContext) objectManager.managedObjectStore = objectStore // -- Declare routes -- // // Login Route objectManager.addResponseDescriptor(userLoginResponseDescriptor()) objectManager.addResponseDescriptor(eventLoginResponseDescriptor()) objectManager.router.routeSet.addRoute(RKRoute(name:kUserLoginRouteName, pathPattern: "/login", method: RKRequestMethod.POST)) } func tearDownRestKit() { // Cancel any network operations and clear the cache RKObjectManager.sharedManager().operationQueue.cancelAllOperations() NSURLCache.sharedURLCache().removeAllCachedResponses() // Cancel any object mapping in the response mapping queue RKObjectRequestOperation.responseMappingQueue().cancelAllOperations() // Ensure the existing defaultStore is shut down NSNotificationCenter.defaultCenter().removeObserver(RKManagedObjectStore.defaultStore()) RKObjectManager.setSharedManager(nil) RKManagedObjectStore.setDefaultStore(nil) } func userMapping() -> RKEntityMapping { let userMapping = RKEntityMapping(forEntityForName: "User", inManagedObjectStore: objectStore) var userDictionary = ["id": "id", "created_at": "createdAt", "updated_at": "updatedAt", "username": "username", "email": "email", "firstname": "firstname", "lastname": "lastname", "organization": "organization"] userMapping.addAttributeMappingsFromDictionary(userDictionary) let tokenMapping = RKEntityMapping(forEntityForName: "ApiToken", inManagedObjectStore: objectStore) tokenMapping.addAttributeMappingsFromArray(["token", "expiration"]) userMapping.addRelationshipMappingWithSourceKeyPath("tokens", mapping:tokenMapping) return userMapping } func userLoginResponseDescriptor() -> RKResponseDescriptor { let userResponseDescriptor = RKResponseDescriptor(mapping: userMapping(), method: RKRequestMethod.POST, pathPattern: "/login", keyPath: "user", statusCodes: NSIndexSet(index: 200)) return userResponseDescriptor } func managedObjectModel() -> NSManagedObjectModel { return NSManagedObjectModel.mergedModelFromBundles(nil) } func optionsForSqliteStore() -> NSDictionary { return [ NSInferMappingModelAutomaticallyOption: true, NSMigratePersistentStoresAutomaticallyOption: true ]; }