我正在编写一个自定义的弹出窗口修饰符(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
}
}
}