在本文中,我想进一步揭示Core Data的功能。本文是续篇。我真的希望我能想到,核心数据不是众多关系数据库之一,而是一个非常强大的工具,可以成为任何自重的IOS开发人员的武器。好吧,让我们开始吧!今天,我们来看一下使用两个NSManageObjectContext和NSFetchedResultsController。两个NSManageObjectContext,为什么需要这样做?
如果您的应用程序主动使用通过其接收数据的任何API,并且您希望将此数据保存在某处,那么Core Data是一个绝佳的选择。您可能会遇到什么问题?第一个也是最明显的-数据量如此之大,以至于当您尝试保存它们时,我们的应用程序将冻结一段时间,这将影响用户的体验。不能在这里省去普通的GCD,因为独立地,这里提到的我们的Core Data Stack是同步工作的,并且对NSManageObjectContext的任何访问都必须等到循环结束。但是这里可以使用在后台线程中运行的私有NSManageObjectContext。为了调用它,您必须首先联系我们的NSPersistentContainer。初始化将如下所示:lazy var persistentContainer: NSPersistentContainer = {
let container = NSPersistentContainer(name: "Preset")
container.loadPersistentStores { (persistent, error) in
if let error = error {
fatalError("Error: " + error.localizedDescription)
}
}
container.viewContext.mergePolicy = NSMergeByPropertyStoreTrumpMergePolicy
container.viewContext.shouldDeleteInaccessibleFaults = true
container.viewContext.automaticallyMergesChangesFromParent = true
return container
}()
合并政策
在这里,您可以指定我们的NSManageObjectContext的合并策略。在这里,我们明确指出核心数据在发生数据冲突时应如何表现。MergePolicy选项:- NSRollbackMergePolicy-发生冲突时,放弃所有更改,直到发生更改为止
- NSOverwriteMergePolicy-保存新值,无论数据如何
- NSMergeByPropertyStoreTrumpMergePolicy-按属性保存更改的对象属性,在这种情况下,将以保存的数据为准
- NSMergeByPropertyObjectTrumpMergePolicy-按属性保存更改的对象属性,在这种情况下,以新数据为准
AutomaticallyMergesChangesFromParent-表示我们的上下文是否将自动合并数据,然后创建一个新的上下文:let context = persistentContainer.viewContext
let context = persistentContainer.newBackgroundContext()
现在我们有两个NSManageObjectContext。第一个用于UI,并在主线程上运行,第二个具有privateQueueConcurrencyType,用于在后台工作。我们将使用它来下载数据。let object = NSEntityDescription.insertNewObject(forEntityName: "Name", into: context)
saveChanges(with: context)
在这里,我们创建实体,然后可以为其分配必要的属性,然后调用save方法,如下所示:func saveChanges(with context: NSManagedObjectContext) {
context.performAndWait {
if context.hasChanges {
do {
try context.save()
} catch {
context.rollback()
}
}
context.reset()
}
}
有两种方法可供选择:- performAndWait-在上下文线程上同步执行操作
- 执行-异步对上下文流执行操作
NSFetchedResultsController
NSFetchedResultsController-执行某些请求并向用户显示必要数据的控制器。lazy var fetchedResultsController: NSFetchedResultsController<Pack> = {
let fetchRequest = NSFetchRequest<Pack>(entityName:"Pack")
fetchRequest.fetchBatchSize = 20
fetchRequest.sortDescriptors = [NSSortDescriptor(key: "name", ascending:true)]
let controller = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: context, sectionNameKeyPath: nil, cacheName: nil)
controller.delegate = self
do {
try controller.performFetch()
} catch {
print(error.localizedDescription)
}
return controller
}()
NSFetchedResultsController有很多配置,我们将分析其中的几个:FetchbatchSizeFetchBatchSize — . Table/CollectionView 5 , 7 , .
FetchbatchSizeFetchBatchSize — .
SortDescriptorSortDescriptor — , .
ReturnObjectsAsFaultsReturnsObjectsAsFaults — , , , PersistentStore RawCache
目前,我们有一个NSFetchedResultsController,它将在表中显示我们的数据。为了更新数据,您需要调用委托方法:extension ViewController: NSFetchedResultsControllerDelegate {
func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, didChange anObject: Any, at indexPath: IndexPath?, for type: NSFetchedResultsChangeType, newIndexPath: IndexPath?) {
collectionView.reloadData()
}
}
当我们对上下文进行任何更改时,此委托方法将起作用。在此实现中,这发生在我们将数据保存在privateContext中之后。此时,将触发委托方法并更新数据。常规数据库中的一些操作和核心数据就成为任何iOS开发人员的强大武器。编码愉快!