RestKit,CoreData和Swift - 我似乎无法获取结果 [英] RestKit, CoreData and Swift - I can't seem to fetch results back out

查看:239
本文介绍了RestKit,CoreData和Swift - 我似乎无法获取结果的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have successfully set up a RestKit to CoreData mapping implementation in a new Swift-based app (currently XCode 6 beta 3). I know the import mappings are working from my RestKit JSON call because I can inspect the sqlite database and see my data. I am unable, however, to get the data back out of the data store in a NSFetchRequest. What am I doing wrong?

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

I'll spare all the RestKit setup and teardown because it's pretty standard and appears to be working great. So here is my AppDelegate query code that doesn't seem to be working:

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:

self.managedObjectContext refers to this from my AppDelegate to get the context from the RestKit shareObject:

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

看起来获取请求是成功的,因为在for / in循环中出现断点。当我检查resultItem或_currentUser对象,但是,它们显示为空,并且if _currentUserNSLog从不触发。

It appears that the fetch request is successful because a breakpoint in the for/in loop occurs. When I inspect the resultItem or _currentUser objects, however, they appear empty and the "if _currentUser" NSLog never fires.

任何想法?

编辑2:

问题源于:我试图将resultItem放入可选。如果声明_currentUser没有可选和删除as?可选的转换查询返回一个合适的User对象:

The problem stems from my attempt to case the resultItem into an Optional. If declare _currentUser without the optional and remove the as? optional cast the query returns a proper User object:

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

EDIT:
我在主要获取请求之前添加了一个记录数,并正确显示了1条记录。所以,我试图将抓取结果映射到我的用户对象的东西是错误的。这是我的用户类:

I added a record count before the main fetch request and it properly shows 1 record. So something is wrong with how I'm trying to map the fetch result into my user object. Here is my user class:

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不喜欢将提取结果作为可选的。我必须把结果放到一个局部变量,然后设置可选:

The answer is that apparently Swift does not like casting the fetch result as an optional. I have to put the result into a local variable and then set the optional:

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的设置和拆卸, )发现有帮助:

Here is my setup and teardown of RestKit in Swift in case anyone (like niiamon) finds it helpful:

从我的RestApi.swift:

From my 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
    ];
}

这篇关于RestKit,CoreData和Swift - 我似乎无法获取结果的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆