【问题标题】:SwiftUI: How to make a CoreData entity conform to a protocol?SwiftUI:如何使 CoreData 实体符合协议?
【发布时间】:2021-02-06 02:29:09
【问题描述】:

我是 CoreData 的新手,但设法将它集成到我的项目中。现在我需要我的一个实体符合我创建的协议。我怎样才能做到这一点?我试过了,但我做错了。

我的协议:

protocol MyProtocol {
    init(text: String)
}

CoreData实体A:

@objc(A)
public class A: NSManagedObject, MyProtocol {
    
    required init(text: String) {
        super.init()                 // Error!
        self.name = text
    }
    
}

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

    @NSManaged public var id: UUID
    @NSManaged public var name: String
}

extension A : Identifiable, CustomStringConvertible {
    var description: String { name }
}

更新: 我需要遵守MyProtocol,因为我有一个可重用的视图,它接受一个“对象”数组,可以向数组中添加/删除项目(CoreData 可能不需要保留这些更改,这些可能只是临时对象)。因此,我需要确保对于传递给此视图的任何对象,都有一种方法可以创建具有此最低要求(文本属性)的相应实例。请参见下面的示例:

struct ReusableView<Element: My Protocol>: View {
    var data: [Element]

    var body: some View {
        //some code

        Button(action: {
            let newElement = Element(text: "test")
            data.append(newElement)
        }, label: {
            Text("Add new Element")
        })

        //more code

        Text("some element name: \(data[0].description)")
    }
}

//... other file

struct MainView: View {
    var entitiesA: [A] //CoreData entity A
    var entitiesB: [B] //CoreData entity B

    var body: some View {
        VStack {
            //some code
            ReusableView(entitiesA)
        
            //some code
            ReusableView(entitiesB)
        }
    }
}

另外,我需要实现协议CustomStringConvertible,以便能够访问“description”属性。

所有这些都适用于 CoreData 对象。这甚至可能吗?我做得对吗?

感谢您的帮助!

【问题讨论】:

  • 你能解释一下为什么你需要一个只有一个 init 的协议,你想实现什么?以及为什么不能将 NSManagedObjectContext 作为参数?
  • 嗨@JoakimDanielson,我已经更新了我的问题的描述。
  • 这不是一个好的解决方案,使用核心数据对象作为临时对象意味着您必须编写代码在视图关闭时删除临时对象,否则它们将在下次您保存到存储中在它们所属的 NSManagedObjectContext 上调用 save()。如果您不这样做,它们将在您下次打开视图和/或启动应用程序时出现。我认为这样的解决方案将很难管理。

标签: core-data swiftui nsmanagedobject


【解决方案1】:

调用指定初始化器

public init(entity: NSEntityDescription, insertInto context: NSManagedObjectContext?)

像这样:

let context: NSManagedObjectContext = NSManagedObjectContext(concurrencyType: NSManagedObjectContextConcurrencyType(rawValue: 0)!) // Your context

@objc(A)
public class A: NSManagedObject, MyProtocol {
    
    required init(text: String) {
        super.init(entity: NSEntityDescription.entity(forEntityName: "A", in: context)!, insertInto: context)
        self.name = text
    }
    
}

注意:Cotext 就是一个例子。使用你的上下文

【讨论】:

  • 嗨@RajaKishan,我已经更新了我的帖子描述,详细介绍了我所面临的问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多