FetchedResults崩溃:调度队列:com.apple.main-thread(0)

时间:2019-12-24 03:36:49

标签: ios swift xcode core-data swiftui

我已经按照本教程学习了动态过滤器和CoreData: https://www.hackingwithswift.com/quick-start/ios-swiftui/dynamically-filtering-fetchrequest-with-swiftui

我有以下代码。 ContentView.swift

import SwiftUI

struct ContentView: View {

    @Environment(\.managedObjectContext) var moc
    @State var lastNameFilter = "A"

    var body: some View {

        VStack {
            FilteredList(filter: lastNameFilter)

            Button("Add Examples") {
                let taylor = Singer(context: self.moc)
                taylor.firstName = "Taylor"
                taylor.lastName = "Swift"

                let ed = Singer(context: self.moc)
                ed.firstName = "Ed"
                ed.lastName = "Sheeran"

                let adele = Singer(context: self.moc)
                adele.firstName = "Adele"
                adele.lastName = "Adkins"

                try? self.moc.save()
            }

            Button("Show A") {
                self.lastNameFilter = "A"
            }

            Button("Show S") {
                self.lastNameFilter = "S"
            }
        }

    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

FilteredList.swift

import CoreData
import SwiftUI

struct FilteredList: View {

    var fetchRequest: FetchRequest<Singer>
    var singers: FetchedResults<Singer> { fetchRequest.wrappedValue }

    var body: some View {
        List(singers, id: \.self) { singer in
            Text("\(singer.wrappedFirstName) \(singer.wrappedLastName)")
        }
    }

    init(filter: String) {
        fetchRequest = FetchRequest<Singer>(entity: Singer.entity(), sortDescriptors: [], predicate: NSPredicate(format: "lastName BEGINSWITH %@", filter))
    }

}

//struct FilteredList_Previews: PreviewProvider {
//    static var previews: some View {
//    }
//}

Singer + CoreDataClass.swift

import Foundation
import CoreData

@objc(Singer)
public class Singer: NSManagedObject {

}

Singer + CoreDataProperties.swift

import Foundation
import CoreData


extension Singer {

    @nonobjc public class func fetchRequest() -> NSFetchRequest<Singer> {
        return NSFetchRequest<Singer>(entityName: "Singer")
    }

    @NSManaged public var firstName: String?
    @NSManaged public var lastName: String?

    var wrappedFirstName : String {
        firstName ?? "Unknown"
    }

    var wrappedLastName : String {
        lastName ?? "Unknown"
    }

}

核心数据具有1个实体:Singer具有2个String属性:firstName和lastName。模块:当前产品模块。密码:手动/无。

当我尝试预览ContentView时,预览崩溃。当我打开崩溃日志文件并转到Debug Navigator时,我会看到以下错误:

  

调度队列:com.apple.main-thread(0)

在线:

FilteredList.swift

var singers: FetchedResults<Singer> { fetchRequest.wrappedValue }

List(singers, id: \.self) { singer in

AppDelegate.swift

class AppDelegate: UIResponder, UIApplicationDelegate {

可能是什么问题?包装的价值?代码有什么问题?

编辑: 这是我的Dropbox上的崩溃日志文件的链接: crash-logs

3 个答案:

答案 0 :(得分:2)

帮助我的是将结构ContentView_Previews(...)更改为:

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
        return ContentView().environment(\.managedObjectContext, context)
    }
}

我也将struct FilteredList_Previews(...)更改为:

struct FilteredList_Previews: PreviewProvider {
    static var previews: some View {
        let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
        return FilteredList(filter: "A").environment(\.managedObjectContext, context)
    }
}

对@Gergely表示感谢,他在这里帮助我解决了类似的问题:https://stackoverflow.com/a/59629730/12315994

答案 1 :(得分:0)

尝试通过以下方式进行初始化:

@FetchRequest(fetchRequest: Singer.fetchRequest())
var singers: FetchedResults<Singer>

...

init(filter: String) {
    _singers = FetchRequest<Singer>(entity: Singer.entity(), 
       sortDescriptors: [], 
       predicate: NSPredicate(format: "lastName BEGINSWITH %@", filter))
}

更新:我无法在本地重现崩溃,因此只能猜测...请参见上面的更新的初始化变量。

答案 2 :(得分:0)

我有同样的情况。提供从AppDelegate到预览的上下文,并向其中添加数据以解决崩溃问题:

struct FilteredList_Previews: PreviewProvider {
  static var previews: some View {
    let moc = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
    let taylor = Singer(context: moc)
    taylor.firstName = "Taylor"
    taylor.lastName = "Swift"
    return FilteredList().environment(\.managedObjectContext, moc)
  }
}

不幸的是,该数据未显示我期望的确切数据(它显示了重复的条目)。但是对我来说,预览视图的设计已经足够了。 希望仍然有帮助。