gpt4 book ai didi

swift - 为什么在 Core Data container.performBackgroundTask() 之后没有触发 tableView.reloadData()

转载 作者:行者123 更新时间:2023-11-28 12:04:22 24 4
gpt4 key购买 nike

我正在使用 Swift 4 构建一个单一 View 的 iOS 11 应用程序,它有一个 UITableViewController,它也被定义为一个 NSFetchedResultsControllerdelegate >.

class MyTVC: UITableViewController, NSFetchedResultsControllerDeleagate {
var container:NSPersistentContainer? =
(UIApplication.shared.delegate as? AppDelegate)?.persistentContainer

var frc : NSFetchedResultsController<Student>?

override func viewDidLoad() {
container?.performBackgroundTask { context in
// adds 100 dummy records in background
for i in 1...100 {
let student = Student(context: context)
student.name = "student \(i)"
}
try? context.save() // this works because count is printed below
if let count = try? context.count(for: Student.fetchRequest()) {
print("Number of students in core data: \(count)") // prints 100
}
} // end of background inserting.

// now defining frc:
if let context = container?.viewContext {
let request:NSFetchRequest<Student> = Student.fetchRequest()
request.sortDescriptors = [NSSortDescriptor(key: "name", ascending: true)]
frc = NSFetchedResultsController<Student> (
fetchRequest: request,
managedObjectContext: context,
sectionNameKeyPath: nil,
cacheName: nil )

try? frc?.performFetch() // this works and I get no errors
tableView.reloadData()
frc.delegate = self
} // end of frc definition
}
}

如果我使用 viewContext 添加一行 Studentfrc 将触发所需的方法以在 中显示它表格 View 。但是,未显示 100 个虚拟行。事实上,如果我试图在插入完成后告诉 tableview 重新加载,我的应用程序开始表现怪异并变得有问题,并且不做它应该做的事情(即:不删除行,不编辑等) .

但是如果我重新启动我的应用程序,而不调用虚拟插入,我可以看到从上一次运行插入的 100 行。

唯一的问题是我不能从后台线程调用tableView.reloadData(),所以我尝试这样做:

// after printing the count, I did this:
DispatchQueue.main.async { [weak self] in
self?.tableView.reloadData() // causes UI to behave weirdly
}

然后我尝试调用 viewContext.perform 以在适当的线程中重新加载 TableView

func viewDidLoad() {

// code for inserting 100 dummy rows in background thread

// code for defining frc and setting self as delegate

if let context = container?.viewContext {
context.perform { [weak self] in
self?.tableView.reloadData() // that also causes UI to behave weirdly

}
}
}

如何告诉我的 tableview 以线程安全的方式重新加载和显示 100 个虚拟行?

最佳答案

override func viewDidLoad() {
super.viewDidLoad()

//Always need your delegate for the UI to be set before calling the UI's delegate functions.
frc.delegate = self

//First we can grab any already stored values.
goFetch()

//This chunk just saves. I would consider putting it into a separate function such as "goSave()" and then call that from an event handler.
container?.performBackgroundTask { context in
//We are in a different queue than the main queue, hence "backgroundTask".
for i in 1...100 {
let student = Student(context: context)
student.name = "student \(i)"
}
try? context.save() // this works because count is printed below
if let count = try? context.count(for: Student.fetchRequest()) {
print("Number of students in core data: \(count)") // prints 100
}
//Now that we are done saving its ok to fetch again.

goFetch()

}

//goFetch(); Your other code was running here would start executing before the backgroundTask is done. bad idea.
//The reason it works if you restart the app because that data you didn't let finish saving is persisted
//So the second time Even though its saving another 100 in another queue there were still at least 100 records to fetch at time of fetch.

}


func goFetch() {

if let context = container?.viewContext {
let request:NSFetchRequest<Student> = Student.fetchRequest()
request.sortDescriptors = [NSSortDescriptor(key: "name", ascending: true)]
frc = NSFetchedResultsController<Student> (
fetchRequest: request,
managedObjectContext: context,
sectionNameKeyPath: nil,
cacheName: nil )

try? frc?.performFetch()

//Now that records are both stored and fetched its safe for our delegate to access the data on the main thread.
//To me it would make sense to do a tableView reload everytime data is fetched so I placed this inside o `goFetch()`
DispatchQueue.main.async { [weak self] in
self?.tableView.reloadData()
}
}
}

关于swift - 为什么在 Core Data container.performBackgroundTask() 之后没有触发 tableView.reloadData(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49714932/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com