核心数据和SwiftUI多态性问题

时间:2020-05-03 18:44:13

标签: swift swiftui

将SwiftUI和通用类型放在一起处理核心数据时遇到了麻烦。

考虑以下示例:

enter image description here

netsh interface ipv4 show excludedportrange protocol=tcp 是抽象的。 ParentFooBar的子级,它们具有一些自定义属性。

现在我想做的大致是:

Parent

我想将多态构建器添加到塑造数据或构建视图的核心数据实体中,以确认通用接口,以便我可以在不进行铸造/键入的情况下使用它们。

如果我尝试不通过扩展直接修改生成的Core数据实体,并通过协议确认(尽管扩展不允许覆盖),则编译器会抛出错误。

1 个答案:

答案 0 :(得分:0)

好吧,这很令人头疼(至少对于Preview来说是疯狂的),但是它可以在运行时运行。在Xcode 11.4 / iOS 13.4上进行了测试。

由于我们需要做所有扩展工作,因此我们的想法是使用通过Obj-C消息传递进行分派,这是在此类要求下可以实际覆盖实现的一种有效途径。

注意:使用模拟器或设备

demo

完整的测试模块

protocol EntityWithView {
    associatedtype T: View
    var buildView: T { get }
}

extension Parent {
    // allows to use Objective-C run-time messaging by complete
    // type erasing.
    // By convention subclasses
    @objc func generateView() -> Any {
        AnyView(EmptyView()) // << safe
        //fatalError("stub in base") // << alternate
    }
}

extension Parent: EntityWithView {
    var buildView: some View {
        // restory SwiftUI view type from dispatched message
        guard let view = self.generateView() as? AnyView else {
            fatalError("Dev error - subview must generate AnyView")
        }
        return view
    }
}

extension Foo {
    @objc override func generateView() -> Any {
        AnyView(Text(footribute ?? ""))
    }
}

extension Bar {
    @objc override func generateView() -> Any {
        AnyView(Text(attribar ?? ""))
    }
}

struct ViewThatUsesCoreDataAsModel: View {
    let entities: [Parent]

    var body: some View {
        VStack {
            ForEach(entities, id: \.self) { entity in
                entity.buildView
            }
        }
    }
}

struct DemoGeneratingViewInCoreDataExtension: View {
    @Environment(\.managedObjectContext) var context
    var body: some View {
        ViewThatUsesCoreDataAsModel(entities: [
           Foo(context: context), 
           Bar(context: context)
        ])
    }
}