Swift中的NSBatchUpdateRequest及其优势
在此博客中,我们将学习实现NSBatchUpdateRequest Swift 3.x版本在iOS 8中引入的Core Data的说明。 我们还将关注内存使用情况和执行时间。 我还制作了有关此主题的视频教程。 请检查博客末尾的链接。
从iOS 8和更高版本以及OS X Yosemite和更高版本,我们可以直接与持久性存储进行交互并更新属性。 根据Apple的说法,这是批量更新。 因此,在不浪费更多时间的情况下,让我们深入了解Xcode中的代码部分。
创建一个新项目,并确保选中使用核心数据复选框。 创建项目后,转到。 xcdatamodeld文件并创建一个名为Student的实体。 我们还将创建它的两个属性, studentName和studentRollNo 。
每当我们尝试从编辑器创建NSManagedObject类时,在Swift 3.x中都会出现一个奇怪的错误- 具有相同名称的文件名redeclaration 。 因此,为了解决该问题,请选择实体,然后在“ 数据检查器”部分中转到“ 类” 。 如下图所示,将Module更改为Current Product Module ,将Codegen
为Manual / None 。
然后,最后单击“编辑器”,然后单击“ 创建NSManagedObject子类”。
因此,我们已经准备好模型子类。 在这里,它们看起来像。
Student + CoreDataClass.swift
进口基金会
导入CoreData
公共班学生:NSManagedObject {
}
Student + CoreDataProperties.swift
进口基金会
导入CoreData
扩展学生{
@nonobjc公共类func fetchRequest()-> NSFetchRequest <学生{
返回NSFetchRequest (entityName:“ Student”);
}
@NSManaged公共var studentName:字符串?
@NSManaged公共var studentRollNo:Int64
}
现在转到视图控制器,我们将在核心数据中添加50,000个学生记录。 让我们来看一下ViewController.swift。 我们将需要一个AppDelegate
共享对象和Core Data context
。
导入UIKit
导入CoreData
类ViewController:UIViewController {
让appDelegate = UIApplication.shared.delegate为! AppDelegate
let context =(UIApplication.shared.delegate as!AppDelegate).persistentContainer.viewContext
覆盖func viewDidLoad(){
super.viewDidLoad()
}
用于插入50,000条记录的功能。 我将学生姓名作为当前日期和卷编号作为for循环的序列值(从1到50,000)插入。
func insert(){
为我in 1…50000 {
让学生= NSEntityDescription.insertNewObject(forEntityName:“ Student”,into:context)为! 学生
student.studentName =“ \(日期())”
student.studentRollNo = Int64(i)
}
appDelegate.saveContext()
}
我们将在viewDidLoad
调用此insert
函数
覆盖func viewDidLoad(){
super.viewDidLoad()
//它将打印由核心数据print(appDelegate.persistentContainer.persistentStoreDescriptions)生成的sqlite文件的实际存储
插入()
}
print(appDelegate.persistentContainer.persistentStoreDescriptions)
将打印的实际路径。 sqlite
文件是。
它将打印如下路径:
/Users/rajan/Library/Developer/CoreSimulator/Devices/B8BD5017–4BD0–47F7-B840-BE9464817392/data/Containers/Data/Application/2B0E7289–1A4C-4F78-AD00–72285B3FA5F9/Library/Application%20Support/yourProjectName.sqlite
我们可以导航到该路径,并可以使用称为SQLite Manager的Firefox简单附件 。 您可以从Firefox的附件中下载它。
单击“ SQLite管理器”,选择“连接到数据库”(黄色文件夹图标),然后导航到控制台上打印到.sqlite
文件的路径。
导航到.sqlite
文件路径
打开.sqlite
文件
您将看到50,000个学生条目。 现在我们插入了记录,将注释掉insert
函数并立即进行更新。
我们将创建一个函数以在ViewController.swift中获取以毫秒为单位的时间
func currentTimeMillis()-> Int64 {
返回Int64(Date()。timeIntervalSince1970 * 1000)
}
现在,我们将创建两种更新方法,一种是批量更新,另一种是旧的传统方法。
//传统方法
func update(){
let request:NSFetchRequest = Student.fetchRequest()
做{
让我们开始= currentTimeMillis()
让searchResults =试试context.fetch(request)
适用于searchResults {
student.studentName =“拉詹”
}
appDelegate.saveContext()
print(“差异为\(currentTimeMillis()-开始)”)
} {
}
}
//使用NSBatchUpdateRequest
func updateWithBatch(){
let request = NSBatchUpdateRequest(entityName:“学生”)
request.propertiesToUpdate = [“ studentName”:“ Rajan Maheshwari”]
request.resultType = .updatedObjectsCountResultType
做{
让我们开始= currentTimeMillis()
让结果=尝试context.execute(request)作为! NSBatchUpdateResult
//将打印受影响/更新的行数
打印(result.result!)
打印(“成功”)
print(“差异为\(currentTimeMillis()-开始)”)
}赶上{
}
}
现在,我们将首先在viewDidLoad
调用update
函数。 这会将50,000名学生的名字更改为Rajan
。 确保注释insert
功能。
覆盖func viewDidLoad(){
super.viewDidLoad()
//插入()
update()
}
结果如下:
它花费了53.8 MB和774毫秒 。 数据库也会更新
现在,通过调用updateWithBatch
使用NSBatchUpdateRequest
进行updateWithBatch
。 注释掉update
和insert
方法。 它将名称从Rajan
更新为Rajan Maheshwari
覆盖func viewDidLoad(){
super.viewDidLoad()
//插入()
// update()
updateWithBatch()
}
结果是:
它花费了大约22.4 MB的时间 ,仅用了91毫秒 。 数据库也将更新。
我们能看到区别吗?
传统方法
内存-53.8 MB
执行时间-774毫秒
使用NSBatchUpdateRequest时
内存-22.4 MB
执行时间-91毫秒
这是使用NSBatchUpdateRequest
的优势
传统方法要求将每条记录加载到内存中,更新记录,并将更改发送到持久性存储。 因此,它将很慢并且消耗大量内存。
在使用NSBatchUpdateRequest
情况下,它直接与持久性存储进行通信,然后在那里修改属性。 Apple建议仅在传统方法过于占用资源或时间的情况下才使用此功能。
因此,批处理请求易于实现,并且在我们即时更新成千上万的属性时非常有用。
影片教学:
有关我在iOS开发上的更多视频教程,请查看我的YouTube频道。