在 Swift 中执行 Restkit addFetchRequestBlock 以进行孤儿删除

Posted

技术标签:

【中文标题】在 Swift 中执行 Restkit addFetchRequestBlock 以进行孤儿删除【英文标题】:Executing Restkit addFetchRequestBlock in Swift for orphan deletion 【发布时间】:2015-08-25 16:22:57 【问题描述】:

(更新:更新代码以实现以下 Wain 的一些建议。)

我一直在努力解决以下问题:我有一个应用程序 - 在 Swift 中 - 使用 Restkit 连接到一个 API,以便在添加/更新事件时下拉事件。下面是一些实现的例子。

API JSON:

[
    
        id: 7,
        title: "Event 1",
        description: "Lorem ipsum dolor...",
    ,
    
        id: 8,
        title: "Event 2",
        description: "Lorem ipsum dolor...",
    
]

AppDelegate:

// Setting up object manager
let baseURL = NSURL(string: "http://url.com")
var objectManager = RKObjectManager(baseURL: baseURL)
objectManager.managedObjectStore = managedObjectStore

// Initialize managed object model and store
var managedObjectModel = NSManagedObjectModel.mergedModelFromBundles(nil)
managedObjectStore = RKManagedObjectStore(managedObjectModel: managedObjectModel)
objectManager.managedObjectStore = managedObjectStore

// Complete CoreData stack initialization
managedObjectStore.createPersistentStoreCoordinator()
let storePath = RKApplicationDataDirectory().stringByAppendingPathComponent("MyApp.sqlite")
let seedPath = NSBundle.mainBundle().pathForResource("RKSeedDatabase", ofType: "sqlite")
var error:NSError?
var persistantStore = managedObjectStore.addSQLitePersistentStoreAtPath(storePath, fromSeedDatabaseAtPath: seedPath, withConfiguration: nil, options: nil, error: nil)

// Creating the managed object contexts
managedObjectStore.createManagedObjectContexts()

// Configure a managed object cache to ensure we don't create duplicate objects
managedObjectStore.managedObjectCache = RKInMemoryManagedObjectCache(managedObjectContext: managedObjectStore.persistentStoreManagedObjectContext)


// Mapping events to Restkit
var eventsMapping = RKEntityMapping(forEntityForName: "Event", inManagedObjectStore: managedObjectStore)
eventsMapping.identificationAttributes = ["eventID", "name", "eventDescription"]
    eventsMapping.addAttributeMappingsFromDictionary([
           "id":"eventID",
           "title":"name",
           "description":"eventDescription"
    ])

// Response descriptor for Events
let eventsDescriptor = RKResponseDescriptor(mapping: eventsMapping, method: RKRequestMethod.GET, pathPattern: "/api/v1/events", keyPath: nil, statusCodes: NSIndexSet(index:200))

// Registering mappings with object manager
objectManager.addResponseDescriptorsFromArray([eventsDescriptor])

数据库模型中的更新方法:

class func runUpdates(completion:(updated:Bool) -> Void) 
   RKObjectManager.sharedManager().getObjectsAtPath("/api/v1/events", parameters: nil,
       success: operation, mappingResult in               
          completion(updated:true)
       ,
       failure: operation, error in
          completion(updated:false)
       
   )

到目前为止,这实际上工作得很好:Restkit 从 API 中提取事件并将它们保存到 Core Data 中,更新更改的事件等很有用。唯一不做的就是删除孤立的事件,所以如果事件在服务器上被删除,它仍保留在我的本地数据中。不好。

所以在谷歌搜索和谷歌搜索并阅读其他 SO 线程之后,第一个想法是如果它是一个 POST 请求,显然 Restkit 不会删除孤儿。只有我肯定在这里发出 GET 请求,如 eventDescriptor 所示。

我遇到的第二件事是显然孤儿只会被 addFetchRequestBlock 删除,所以显然我不应该使用 getObjectsAtPath。在 Swift 中这样的例子非常稀少和缺乏,但是基于 Objective C 的例子我想出了这个来替换 getObjectsAtPath。

RKObjectManager.sharedManager().addFetchRequestBlock  (url:NSURL!) -> NSFetchRequest! in
   var pathMatcher = RKPathMatcher(pattern: "/api/v1/events")
   var match = pathMatcher.matchesPath(url.relativePath, tokenizeQueryStrings: false, parsedArguments: nil)
   if(match) 
      var fetchRequest = NSFetchRequest(entityName: "Event")
      return fetchRequest
    else 
      return nil
   

但是,它根本不起作用:它自动返回 nil(甚至在检查 pathMatcher 以尝试查看它在做什么之前忽略 pathMatcher 周围的任何中断线程)。

很明显,我忽略了某些事情或没有以正确的方式编写方法/做错了什么,有什么想法吗?

【问题讨论】:

【参考方案1】:

您对获取请求块的用途有些困惑。它在那里找到可以删除的对象,但它与下载无关。因此,您在配置映射时配置块,然后在您的 GET 完成后开始操作以整理旧(孤立)项目。

顺便说一句,您真的应该在映射上使用identificationAttributes,并创建一个RKInMemoryManagedObjectCache 用作存储managedObjectCache。这允许在收到新内容时正确匹配现有项目。

【讨论】:

谢谢你。除了上述建议之外,我还需要为 Restkit 更新一些核心数据堆栈内容(它仍在使用一些默认样板文件)。我在 AppDelegate 中的映射之后放置了获取请求块,并且它确实在 getObjects 方法运行时被调用。从那里,它能够成功删除我从服务器中删除的事件。现在唯一的问题是我在表(NSFetchedResultsController)上遇到断言失败,但超出了原始问题的范围,根据上述更改,我仍然需要先更新一些内容。再次感谢。 只是向可能有类似问题的任何人简单提一下:我在上面的回复评论中提到的断言失败仅仅是由于我的 NSFetchedResultsController 方法中的一个问题,与 RestKit 无关。因此,如果您有类似的问题,请检查您的 didChangeObject / didChangeSection 方法并确保正确定义了相应的 Insert / Delete / etc 情况。

以上是关于在 Swift 中执行 Restkit addFetchRequestBlock 以进行孤儿删除的主要内容,如果未能解决你的问题,请参考以下文章

没有带有 cocoapods 和 swift 的模块“RestKit”

RestKit:映射类在 Swift 中为零

Swift RestKit Post 不包括帖子数据

Restkit, Swift, Core data 一对多

RestKit 编译失败,cocoapods use_frameworks for swift

RestKit RKObjectMapping Swift 可选