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

Executing Restkit addFetchRequestBlock in Swift for orphan deletion

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

我一直在与以下问题作斗争:我有一个应用程序 - 在 Swift 中 - 连接到 API 和 Restkit 以按原样拉下事件 added/updated .下面是一些实现的例子。

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 中提取事件并将它们保存到核心数据中,更新更改的事件等很有用。唯一不做的就是删除孤立的事件,因此如果在服务器上删除了一个事件,它仍保留在我的本地数据中。不好。

所以在谷歌搜索和谷歌搜索以及阅读其他 SO 线程之后,第一个想法是如果它是 POST 请求,Restkit 显然不会删除孤儿。正如在 eventDescriptor 中看到的那样,只有我肯定会在此处发出 GET 请求。

我遇到的第二件事是显然只有使用 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
   }
}

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

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

您对获取请求块的用途有点困惑。它是用来查找可以删除的对象的,与下载无关。因此,您在配置映射时配置块,然后在 GET 完成后它开始运行以整理旧的(孤立的)项目。

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