我對我的項目和我的數據庫使用MagicalRecord我有CDSong實體,可以由多個CDVoter實體投票。 MagicalRecord數據庫與NSFetchedResultsController不一致
選民在後臺添加和刪除使用從串行調度隊列調用的NSManagedObjectContext.performAndWait(block:)
。我有一個NSFetchedResultsController
,它提取CD歌曲並顯示他們的選民(在這種簡單的情況下,它只打印選民的名字)。
一切都會好起來的,但偶爾會在NSFetchedResultsControllerDelegate的controllerDidChangeContent方法中收到崩潰: - 根據我的分析,似乎在CDSong.voters關係中出現了一些無效的空CDVoter(name = nil,votedSong = nil)對象。這些空選票不會從CDVoter.mr_findAll()
返回。
這是模擬崩潰的代碼(通常在按鈕點擊應用程序崩潰後,因爲CDVoter的名稱爲零)。我的上下文是否有問題並保存?將整個測試代碼放在這裏用數據庫和frc初始化,如果有人想嘗試一下,但問題部分在controllerDidChangeContent
和buttonPressed
方法。感謝您的幫助:)
import UIKit
import CoreData
import MagicalRecord
class MRCrashViewController : UIViewController, NSFetchedResultsControllerDelegate {
var frc: NSFetchedResultsController<NSFetchRequestResult>!
let dispatchQueue = DispatchQueue(label: "com.testQueue")
override func viewDidLoad() {
super.viewDidLoad()
self.initializeDatabase()
self.initializeFrc()
}
func initializeDatabase() {
MagicalRecord.setLoggingLevel(MagicalRecordLoggingLevel.error)
MagicalRecord.setupCoreDataStack()
MagicalRecord.setLoggingLevel(MagicalRecordLoggingLevel.warn)
if CDSong.mr_findFirst() == nil {
for i in 1...5 {
let song = CDSong.mr_createEntity()!
song.id = Int16(i)
}
}
NSManagedObjectContext.mr_default().mr_saveToPersistentStoreAndWait()
}
func initializeFrc() {
let fetchRequest: NSFetchRequest<NSFetchRequestResult> = NSFetchRequest(entityName: "CDSong")
fetchRequest.sortDescriptors = [NSSortDescriptor(key: "id", ascending: true)]
NSFetchedResultsController<NSFetchRequestResult>.deleteCache(withName: nil)
self.frc = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: NSManagedObjectContext.mr_default(), sectionNameKeyPath: nil, cacheName: nil)
self.frc!.delegate = self
try! self.frc!.performFetch()
}
func controllerDidChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
for song in controller.fetchedObjects! {
print((song as! CDSong).voters!.reduce("", { $0 + ($1 as! CDVoter).name! }))
}
print("----");
}
@IBAction func buttonPressed(_ sender: Any) {
for _ in 1...10 {
self.dispatchQueue.async {
let moc = NSManagedObjectContext.mr_()
moc.performAndWait {
for song in CDSong.mr_findAll(in: moc)! {
let song = song as! CDSong
let voters = song.voters!
for voter in voters {
(voter as! CDVoter).mr_deleteEntity(in: moc)
}
for _ in 1...4 {
if arc4random()%2 == 0 {
let voter = CDVoter.mr_createEntity(in: moc)!
voter.name = String(UnicodeScalar(UInt8(arc4random()%26+65)))
voter.votedSong = song
}
}
}
moc.mr_saveToPersistentStoreAndWait()
}
}
}
}
}
注: 我試圖用MagicalRecord.save(blockAndWait :)沒有成功。
「選民使用串行調度隊列在後臺添加和刪除」。你應該**不要使用你自己的隊列**作爲coredata。你應該只使用NSManagedObjectContext的PerformBlock方法**。 – 2017-08-30 12:36:42
@Sneak我使用performBlockAndWait方法來處理核心數據,但是我從一個bg隊列中調用它們。我認爲這是可以的,至少[docs](https://developer.apple.com/documentation/coredata/nsmanagedobjectcontext)不會說我只能從主線程調用performBlockAndWait,他們只是說我應該調用方法來自我創建上下文的同一個線程。我必須使用bg隊列,因爲performBlockAndWait會阻止圖形,如果從主調用執行只會混合刪除和插入(相信我,只是試了一下)。謝謝,我將編輯句子 –
刪除我的意見,這將解決您的問題,而不是打字。因爲你對「句子編輯」和「相信我」非常傲慢,而不是質疑我的觀點並試圖學習某些東西。祝你好運。 – 2017-08-30 13:53:46