ios - RestKit、CoreData 和 Swift - 我似乎无法取回结果

标签 ios core-data swift restkit

我已经在一个新的基于 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
}

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

有什么想法吗?我是否对在 Swift 中取回数据做出了错误的假设?

编辑 2:

问题源于我试图将 resultItem 转换为 Optional。如果在没有可选的情况下声明 _currentUser 并删除 as?可选转换查询返回一个正确的用户对象:

        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)觉得它有用:

来 self 的 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
    ];
}

关于ios - RestKit、CoreData 和 Swift - 我似乎无法取回结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24736739/

相关文章:

ios - 如何使用Sprite Kit创建弯曲的水平边界

ios - NotificationCenter 没有调用选择器

ios - 在多个线程上访问 ViewContext 导致崩溃

ios决定是否在客户端代码的某些条件下静音我的远程通知,而不是设置内容可用

swift - 对字典数组进行排序

ios - 如何将Manual Retain-Release代码自动转换为ARC?

ios - 当应用程序在后台使用 Sinch iOS SDK 时无法处理来电推送通知

ios - 如何检查关系是否已经建立 - Core Data

iphone - 如何创建神奇的 .xcdatamodeld 文件夹/包?

ios - 求三次贝塞尔曲线上一点的正切