SwiftUI:ForEach of FetchedResults 给出错误 - “'NSManagedObject' 类型的值没有成员......”

Oth*_*hyn 13 swift swiftui

我是 SwiftUI 的新手,部分是 Swift,所以希望有人能对我明显缺少的东西有所了解。原谅乱码!我还没有机会重构。

我正在使用@FetchRequest属性包装器MemoriesCoreData模型中拉回所有列表,并在NSFetchRequest<Memory>其上定义了一个方法,从NSManagedObject.

当我FetchRequest<Memory>通过 a遍历in SwiftUI的结果时ForEach,它会将 的实例返回NSManagedObject到循环变量中,而不是 of Memory,因此显示错误:Value of type 'NSManagedObject' has no member 'createdAt'对于以下 SwiftUI 类:

import SwiftUI

struct MemoryView: View {

    @Environment(
        \.managedObjectContext
    ) var managedObjectContext

    @FetchRequest(
        fetchRequest: Memory.allMemories()
    ) var allMemories: FetchedResults<Memory>

    @State private var newMemory = ""

    var body: some View {
        NavigationView {
            List {
                Section(header: Text("What's on your mind?")) {
                    HStack {
                        TextField("New memory", text: self.$newMemory)

                        Button(action: {
                            let memory = Memory(context: self.managedObjectContext)

                            memory.title = self.newMemory
                            memory.createdAt = Date()

                            do {
                                try self.managedObjectContext.save()
                            } catch {
                                print(error)
                            }

                            self.newMemory = ""
                        }) {
                            Image(systemName: "plus.circle.fill")
                                .foregroundColor(.green)
                                .imageScale(.large)
                        }
                    }
                }
                .font(.headline)

                Section(header: Text("My Memories")) {
                    ForEach(self.allMemories) { memoryItem in
                        MemoryRow(title: memoryItem.title, createdAt: memoryItem.createdAt)
                        //               /\ /\ /\ /\ /\ /\            /\ /\ /\ /\ /\ /\ /\
                        // >>> Error:
                        // >>> Value of type 'NSManagedObject' has no member 'createdAt'
                    }
                }
            }
            .navigationBarTitle(Text("Memories"))
            .navigationBarItems(trailing: EditButton())
        }
    }
}

struct MemoryView_Previews: PreviewProvider {
    static var previews: some View {
        MemoryView()
    }
}
Run Code Online (Sandbox Code Playgroud)

作为参考,有Memory问题的模型如下:

import Foundation
import CoreData
import CoreLocation

// Define the CoreData Object Model.
// Ensuring that this class name matches
// the entity model name.
public class Memory: NSManagedObject, Identifiable {
    @NSManaged public var title: String?
    @NSManaged public var body: String?

    @NSManaged public var latitude: Double
    @NSManaged public var longitude: Double

    @NSManaged public var createdAt: Date?
    @NSManaged public var updatedAt: Date?

//    @NSManaged public var type: Type?
//    @NSManaged public var tags: [Tags]?
}

// Create an extension in which to place things out of the context
// of the initial class declaration within.
extension Memory {
    // Define a helper method for accessing a generated
    // CLLocationCoordinate2D instance from the objects
    // latitude and longitude values.
    var locationCoordinate: CLLocationCoordinate2D {
        CLLocationCoordinate2D(
            latitude: latitude,
            longitude: longitude
        )
    }

    // Define a helper method that grabs all instances of a Memory
    // sorted by their created date in ascending order.
    static func allMemories() -> NSFetchRequest<Memory> {
        let request: NSFetchRequest<Memory> = Memory.fetchRequest() as! NSFetchRequest<Memory>

        let sortDescriptor = NSSortDescriptor(key: "createdAt", ascending: true)

        request.sortDescriptors = [sortDescriptor]

        return request
    }
}
Run Code Online (Sandbox Code Playgroud)

对此的任何帮助将不胜感激,因为我完全没有想法。我认为明天的问题有一个新的头脑!

编辑:这是MemoryRow课程:

import SwiftUI

struct MemoryRow: View {
    var title: String = ""
    var createdAt: String = ""

    var body: some View {
        HStack {
            VStack(alignment: .leading) {
                Text(title)
                    .font(.headline)

                Text(createdAt)
                    .font(.caption)
            }
        }
    }
}

struct MemoryRow_Previews: PreviewProvider {
    static var previews: some View {
        MemoryRow(title: "Test Title", createdAt: "Test Date")
    }
}
Run Code Online (Sandbox Code Playgroud)

iRi*_*iya 16

就我而言,这是因为optional我们在数据模型中添加属性时默认选择的数据类型,因此NSManagedObjectClass它看起来像这样

@NSManaged public var name: String?

当然,要解决这个问题,可以?从上面的行中删除或??在使用该属性时使用nil 合并运算符,例如ClassName.name ?? "Unknown"

根据给出的答案和评论,我在课堂上检查了我的属性名称是否有任何错字,然后我意识到了这个问题。现在必须处理这种行为SwiftUI,它不会显示实际错误或将显示在任何其他行上。

希望这可以帮助像我这样的人。


Hit*_*wal 8

在闭包参数中设置 NSManagedObject 类型。

ForEach(books, id: \.self) { book in 
     //
}
Run Code Online (Sandbox Code Playgroud)

ForEach(books, id: \.self) { (book: Book) in
     //
}
Run Code Online (Sandbox Code Playgroud)


Oth*_*hyn 6

我实际上对什么为我解决了这个问题感到有些困惑。以下是我在它“起作用”之前所做的一些事情

我不知道是哪个原因造成的,我刚刚重新打开 Xcode,之前失败的构建现在意外地再次构建

因此,急于思考我做了什么来修复它并使用 Git 差异作为某种形式的参考,这是我按以下顺序重新跟踪我的步骤:

  1. 检查在视图attachementSceneDelegatecontentView,为此,ViewNSManagedObjectContext上下文被曝光到。这对View我来说是错误的,它被附加到MemoryDetail()not MemoryList()

  2. 删除了违规行:

MemoryRow(title: memoryItem.title!, createdAt: memoryItem.description)
Run Code Online (Sandbox Code Playgroud)

并用填充物替换它,Text("test")成功保存和构建项目。

  1. sortDescriptor声明更改为:
let sortDescriptor = NSSortDescriptor(key: "createdAt", ascending: true)

request.sortDescriptors = [sortDescriptor]
Run Code Online (Sandbox Code Playgroud)

request.sortDescriptors = [
    NSSortDescriptor(key: "createdAt", ascending: true)
]
Run Code Online (Sandbox Code Playgroud)
  1. 重新启动 Xcode(尽管多次这样做但无论如何都无济于事)。

  2. 暂存,而不是提交,我跟踪的代码更改。

  3. 删除填充符Text("test")并手动输入该行:

MemoryRow(title: memoryItem.title!, createdAt: memoryItem.description)
Run Code Online (Sandbox Code Playgroud)

其中代码提示仍然不起作用,但该行现在构建良好,因此您必须手动执行。不,解包力!不是错误的原因。


编辑:

在使用 Git 差异并粘贴我的原始代码后,我想我知道错误是什么:

MemoryRow(title: memoryItem.title!, createdAt: memoryItem.createdAt)
//                                                        ^^^^^^^^^
// This is wrong ----------------------------------------//////////
Run Code Online (Sandbox Code Playgroud)

它没有帮助,因为编译器给出的错误与实际问题没有直接关系。错误应该memoryItem.createdAt是没有返回MemoryRow.

MemoryRow(title: memoryItem.title!, createdAt: "")
// Compiles fine

// And now the corrected version:
MemoryRow(title: memoryItem.title!, createdAt: "\(memoryItem.createdAt!)")
Run Code Online (Sandbox Code Playgroud)

我认为问题是 Xcode 有时会出现一些偶然的错误。

我已经修改了MemoryRow现在接受Date?类型而不是String?实际上更好地描述对象正在接受的内容。连同解包、格式化和呈现该类中的变量。