SwiftUI ViewModifier的延迟加载

时间:2020-06-04 10:12:28

标签: ios swiftui

我正在编写一个自定义的弹出窗口修饰符(SwiftUI警报样式),因此我希望使用延迟加载,以便仅在屏幕上开始显示弹出窗口后才加载其内容。我正在测试一个简单的示例,从理论上讲,该示例仅应在我按下按钮后崩溃,但在启动时崩溃,这意味着popup的body builder调用得太早了。

在此代码示例中,我尝试将弹出窗口的内容包装到LazyView中,人们在有关NavigationLinks的类似问题中建议使用此方法,但这似乎无济于事。我还尝试将@autoclosure添加到所有可以想到的参数中,但是没有成功。

P.S。这只是一个最小的示例,原始代码更加复杂,如果isPresented = false无法正常工作,则必须隐藏所有内容,因为弹出窗口必须设置动画。

extension View {

    public func popup<PopupContent: View>(
        isPresented: Binding<Bool>,
        view: @escaping () -> PopupContent) -> some View {
        self.modifier(
            Popup(
                isPresented: isPresented,
                view: view)
        )
    }
}

public struct Popup<PopupContent>: ViewModifier where PopupContent: View {

    @Binding var isPresented: Bool

    var view: () -> PopupContent

    public func body(content: Content) -> some View {
        content.overlay(LazyView(self.view()))
    }
}

struct LazyView<Content: View>: View {
    let build: () -> Content
    init(_ build: @autoclosure @escaping () -> Content) {
        self.build = build
    }
    var body: Content {
        build()
    }
}

struct ContentView: View {
    @State private var showingAlert = false
    let data: String? = nil
    var body: some View {
        Button(action: {
            self.showingAlert = true
        }) {
            Text("Show Alert")
        }
        .popup(isPresented: $showingAlert) {
            Text(self.data!) // crash here
        }
    }
}

0 个答案:

没有答案