在SwiftUI中找不到子Shape的EnvironmentObject

时间:2020-04-15 09:51:18

标签: swiftui

与自定义@EnvironmentObject一起使用时,我遇到以下Shape的SwiftUI错误:

Fatal error: No ObservableObject of type MyObject found. A View.environmentObject(_:) for MyObject may be missing as an ancestor of this view.: file SwiftUI, line 0

只有当我使用任何Shape方法返回实例的新副本(例如stroke())时,这种情况才会发生。

这里是一个Swift游乐场示例,可以重现:

import SwiftUI
import PlaygroundSupport

class MyObject: ObservableObject {
    @Published var size: Int = 100
}

struct MyShape: Shape {
    @EnvironmentObject var envObj: MyObject

    func path(in rect: CGRect) -> Path {
        let path = Path { path in
            path.addRect(CGRect(x: 0, y: 0,
                                width: envObj.size, height: envObj.size))
        }
        return path
    }
}

struct MyView: View {
    var body: some View {
        MyShape().stroke(Color.red) // FAIL: no ObservableObject found
        // MyShape() // OK: it works
    }
}

let view = MyView().environmentObject(MyObject())
PlaygroundPage.current.setLiveView(view)

由于似乎未复制环境字段,因此我也尝试过这样明确地做到这一点:

struct MyView: View {
    @EnvironmentObject var envObj: MyObject

    var body: some View {
        MyShape().stroke(Color.red).environmentObject(self.envObj)
    }
}

它仍然失败。作为SwiftUI的初学者,除了不使用环境之外,我不知道这是否是预期的行为,是否不继承视图层次结构环境以及如何处理它。

有什么主意吗?

1 个答案:

答案 0 :(得分:4)

问题实际上是.stroke在构造函数之后被称为 ,因此在注入environmentObject之前(如果注释掉笔画,您可以测试它是否有效)。但是.stroke不能在注入环境对象之后添加 ,因为.strokeShape-only修饰符。

解决方案是在构造过程中注入依赖项,如下所示。使用Xcode 11.4 / iOS 13.4进行了测试

struct MyShape: Shape {
    @ObservedObject var envObj: MyObject
...
}

struct MyView: View {
    @EnvironmentObject var envObj: MyObject
    var body: some View {
        MyShape(envObj: self.envObj).stroke(Color.red)
    }
}