Chr*_*s G 4 swiftui swift-optionals observedobject
为了提供一些背景信息,我正在编写我们应用程序的订单跟踪部分,该部分会经常从服务器重新加载订单状态。屏幕上的 UI 是用 SwiftUI 开发的。我需要屏幕上有一个可选图像,该图像随着订单的进展而变化。
当我尝试以下操作时,一切正常......
我的 viewModel 是一个 ObservableObject:
internal class MyAccountOrderViewModel: ObservableObject {
这有一个已发布的属性:
@Published internal var graphicURL: URL = Bundle.main.url(forResource: "tracking_STAGEONE", withExtension: "gif")!
在 SwiftUI 中使用该属性如下:
GIFViewer(imageURL: $viewModel.graphicURL)
我的问题是该graphicURL属性的占位符值可能不正确,而我的要求是它是可选的。将已发布的属性更改为:@Published internal var graphicURL: URL?会导致我的 GIFViewer 出现问题,它不接受可选 URL:
Cannot convert value of type 'Binding<URL?>' to expected argument type 'Binding<URL>'
尝试明显展开 会graphicURL产生此错误:
Cannot force unwrap value of non-optional type 'Binding<URL?>'
使这项工作有效的正确方法是什么?我不想在属性中添加一个值,并检查该属性是否等于占位符值(即将其视为 nil),或者假设该属性始终为非 nil 并以某种方式不安全地强制解开它。
Binding下面是您可以用来将类型转换Binding<Int?>为的扩展Binding<Int>?。在您的情况下,它将URL代替Int,但此扩展是通用的,因此可以与任何Binding:
extension Binding {
func optionalBinding<T>() -> Binding<T>? where T? == Value {
if let wrappedValue = wrappedValue {
return Binding<T>(
get: { wrappedValue },
set: { self.wrappedValue = $0 }
)
} else {
return nil
}
}
}
Run Code Online (Sandbox Code Playgroud)
以示例视图:
struct ContentView: View {
@StateObject private var model = MyModel()
var body: some View {
VStack(spacing: 30) {
Button("Toggle if nil") {
if model.counter == nil {
model.counter = 0
} else {
model.counter = nil
}
}
if let binding = $model.counter.optionalBinding() {
Stepper(String(binding.wrappedValue), value: binding)
} else {
Text("Counter is nil")
}
}
}
}
class MyModel: ObservableObject {
@Published var counter: Int?
}
Run Code Online (Sandbox Code Playgroud)
结果:
| 归档时间: |
|
| 查看次数: |
3313 次 |
| 最近记录: |