(更新:更新了以下代码以实现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周围的任何中断线程,试着看看它在做什么)。
显然,我忽略了某些事情,或者没有以正确的方式编写方法/做错事,任何关于什么的想法?
答案 0 :(得分:1)
您对获取请求块的用途有点困惑。它可以找到可以删除的对象,但它与下载无关。因此,您在配置映射时配置块,然后在GET完成后将其置于操作中以整理旧的(孤立的)项目。
另外,您应该在映射上使用identificationAttributes
并创建RKInMemoryManagedObjectCache
以用作商店managedObjectCache
。这样可以在收到新内容时正确匹配现有项目。