今天我正在进行简单的测试
func testCountSales() {
measureMetrics([XCTPerformanceMetric_WallClockTime], automaticallyStartMeasuring: false, for: {
let employee = self.getEmployees()
let employeeDetails = EmployeeDetailViewController()
self.startMeasuring()
_ = employeeDetails.salesCountForEmployees(employee)
self.stopMeasuring()
})
}
func getEmployees() -> Employee {
let coreDataStack = CoreDataStack(modelName: "EmployeeDirectory")
let request: NSFetchRequest<Employee> = NSFetchRequest(entityName: "Employee")
request.sortDescriptors = [NSSortDescriptor(key: "guid", ascending: true)]
request.fetchBatchSize = 1
let results: [AnyObject]?
do {
results = try coreDataStack.mainContext.fetch(request)
} catch _ {
results = nil
}
return results![0] as! Employee
}
我想知道fetchBachSize真的有效吗?我试图看到调试部分是完整的数组(50个元素,因为它应该是)。所有这些都是错误。好。然后我尝试添加Observer for FetchedResultsController的fetchedObject的计数属性
var window: UIWindow?
lazy var coreDataStack = CoreDataStack(modelName: "EmployeeDirectory")
let amountToImport = 50
let addSalesRecords = true
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey : Any]?) -> Bool {
importJSONSeedDataIfNeeded()
guard let tabController = window?.rootViewController as? UITabBarController,
let employeeListNavigationController = tabController.viewControllers?[0] as? UINavigationController,
let employeeListViewController = employeeListNavigationController.topViewController as? EmployeeListViewController else {
fatalError("Application storyboard mis-configuration. Application is mis-configured")
}
employeeListViewController.coreDataStack = coreDataStack
employeeListViewController.addObserver(self, forKeyPath: "fetchedResultsController", options: [.new], context: nil)
guard let departmentListNavigationController = tabController.viewControllers?[1] as? UINavigationController,
let departmentListViewController = departmentListNavigationController.topViewController as? DepartmentListViewController else {
fatalError("Application storyboard mis-configuration. Application is mis-configured")
}
departmentListViewController.coreDataStack = coreDataStack
return true
}
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
if keyPath == "fetchedResultsController" {
print ("Gold")
let a = window?.rootViewController as? UITabBarController
let employeeListNavigationController = a?.viewControllers?[0] as? UINavigationController
let b = employeeListNavigationController?.topViewController as? EmployeeListViewController
print( b?.fetchedResultsController.fetchedObjects?.count)
}
}
它告诉我,它立刻就是零了。显然它们也是缺点。那么为什么我们需要fetchBatchSize以及什么时候玩呢?如何?如果有人有任何想法我会非常感激
答案 0 :(得分:1)
当您指定非零fetchBatchSize
来请求核心数据将查询底层持久性存储并且在接收结果时,仅将结果数组的fetchBatchSize
范围内的对象提取到其他内存中数组中的条目是页面错误。
引用苹果:
如果设置非零批量大小,则返回对象集合 当执行NSFetchRequest的实例被分成批次时。 执行提取时,将评估整个请求并执行 记录的所有匹配对象的标识,但仅包含对象的数据 直到batchSize将从a的持久存储中获取 时间。从执行请求返回的数组是代理对象 根据需要透明地对批次进行故障处理。 (在数据库方面,这个 是一个内存中的游标。)
例如,假设您的查询结果为1000个对象的数组,并且您将fetchBatchSize
指定为50.然后,在1000个对象中,只有前50个将转换为实际的对象/实体,并将被加载到内存中。而剩下的950只是一个页面错误。当你的代码试图访问前50个对象时,对象将直接从内存中访问,当你的代码试图访问第51个对象时,因为对象不在内存中(因此页面错误)核心数据将优雅地构造对象从持久存储中获取下一批数据并将其返回给您的代码。
使用fetchBatchSize
,您可以在处理大型数据集时控制在内存中处理的对象数。
它告诉我,它现在是零,然后立即50。显然他们 也是错误。
我相信你期待FetchedResultsController
获取1个对象,因为你将fetchBatchSize
指定为1.但它最终获得了50个。所以你现在感到困惑不是吗?
fetchBatchSize
不会改变FetchedResultsController
的获取对象数,它只会影响搜索结果中实际加载到内存中的对象数。如果你真的想控制FetchedResultsController
提取的对象数量,你应该考虑使用fetchLimit
阅读:
https://developer.apple.com/documentation/coredata/nsfetchrequest/1506622-fetchlimit
引用苹果:
获取限制指定请求的最大对象数 应该在执行时返回。如果设置了提取限制,那么框架 尽最大努力提高效率,但不保证。 对于除SQL存储之外的每个对象存储,都会执行获取请求 有效的提取限制只是执行无限制的提取和 抛弃未使用的行
希望有所帮助