在 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
。这允许在收到新内容时正确匹配现有项目。
(更新:更新代码以实施下面 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
。这允许在收到新内容时正确匹配现有项目。