Swiftui 如何从Swift类更改@State变量
我有SwiftUI ContentView结构,从中调用标准Swift类中的函数。此函数可能会抛出一个错误,我希望通过ContentView中的Alert显示该错误。警报的外观由ContentView中声明的Bool@State var控制。 我试图在函数中使用@Binding属性包装器,但显然不正确。我应该使用ObservieObject还是最好的方法? 谢谢 带有警报的ContentView片段Swiftui 如何从Swift类更改@State变量,swiftui,Swiftui,我有SwiftUI ContentView结构,从中调用标准Swift类中的函数。此函数可能会抛出一个错误,我希望通过ContentView中的Alert显示该错误。警报的外观由ContentView中声明的Bool@State var控制。 我试图在函数中使用@Binding属性包装器,但显然不正确。我应该使用ObservieObject还是最好的方法? 谢谢 带有警报的ContentView片段 HStack { Button("Load data...", ac
HStack {
Button("Load data...", action: {
let panel = NSOpenPanel()
panel.title = "Select CSV formatted data file"
panel.canChooseFiles = true
panel.allowedFileTypes = ["csv"]
panel.allowsMultipleSelection = false
panel.begin(completionHandler: {result in
if result == .OK {
getDataset(fromFileURL: panel.url!, withHeaderLine: headerLine)
}
})
})
.padding()
.alert(isPresented: $isError, content: {
Alert(title: Text("Error"), message: Text(errorText), dismissButton: .default(Text("OK")))
})
Toggle("With header line", isOn: $headerLine)
}.toggleStyle(SwitchToggleStyle())
}
可能引发错误的被调用函数的片段
do {
var fromRow = 0
let fileContent = try String(contentsOf: fromFileURL)
let rows = fileContent.components(separatedBy: "\n")
if withHeaderLine { fromRow = 1 }
for i in fromRow...rows.count - 1 {
let columns = rows[i].components(separatedBy: ",")
guard let xValue = Double(columns[0]) else {
throw myError.conversionFailed
}
guard let yValue = Double(columns[1]) else {
throw myError.conversionFailed
}
myDataset.append(Dataset(x: xValue, y: yValue))
}
} catch myError.conversionFailed {
errorText = "Value conversion to Double failed."
isError.toggle()
} catch let error {
errorText = error.localizedDescription
isError.toggle()
}
}
我建议为该视图创建一个ViewModel。在该ViewModel中,您为errorText和iError创建了两个PublishedValue。然后,可以在ViewModel中使用该函数并更新发布的值。ViewModel将如下所示,然后相应地更新其他视图
class ContentViewModel : ObservableObject {
@Published var isError : Bool = false
@Published var errorText : String = ""
func getDataset() {
//Here you call your function and return the result or call it directly inside here
errorText = "Value conversion to Double failed." //<< here you can change published values
isError.toggle()
}
}
如果仍然将函数外包到另一个视图中,只需从该函数返回错误字符串或使用闭包即可。我建议为该视图创建一个ViewModel。在该ViewModel中,您为errorText和iError创建了两个PublishedValue。然后,可以在ViewModel中使用该函数并更新发布的值。ViewModel将如下所示,然后相应地更新其他视图
class ContentViewModel : ObservableObject {
@Published var isError : Bool = false
@Published var errorText : String = ""
func getDataset() {
//Here you call your function and return the result or call it directly inside here
errorText = "Value conversion to Double failed." //<< here you can change published values
isError.toggle()
}
}
如果您仍然将函数外包到另一个视图中,只需从该函数返回错误字符串或使用闭包即可。下面是一个可能方法的演示(如果有必要,可以模拟异步调用) 使用Xcode 12.1/iOS 14.1进行测试
class DemoClass {
func simulate(isError: Binding<Bool>) {
DispatchQueue.global(qos: .background).async {
sleep(1)
DispatchQueue.main.async {
isError.wrappedValue.toggle()
}
}
}
}
struct ContentView: View {
let demo = DemoClass()
@State private var isError = false
var body: some View {
VStack {
Button("Demo") { demo.simulate(isError: $isError) }
}
.alert(isPresented: $isError, content: {
Alert(title: Text("Error"), message: Text("errorText"), dismissButton: .default(Text("OK")))
})
}
}
class演示类{
func模拟(iError:Binding){
DispatchQueue.global(qos:.background).async{
睡眠(1)
DispatchQueue.main.async{
isError.wrappedValue.toggle()文件
}
}
}
}
结构ContentView:View{
让demo=DemoClass()
@国家私有变量isError=false
var body:一些观点{
VStack{
按钮(“Demo”){Demo.simulate(isError:$isError)}
}
.alert(显示:$isError,内容:{
警报(标题:文本(“错误”)、消息:文本(“错误文本”)、解除按钮:。默认值(文本(“确定”))
})
}
}
这里是一个可能的方法的演示(如果有必要,可以模拟异步调用)
使用Xcode 12.1/iOS 14.1进行测试
class DemoClass {
func simulate(isError: Binding<Bool>) {
DispatchQueue.global(qos: .background).async {
sleep(1)
DispatchQueue.main.async {
isError.wrappedValue.toggle()
}
}
}
}
struct ContentView: View {
let demo = DemoClass()
@State private var isError = false
var body: some View {
VStack {
Button("Demo") { demo.simulate(isError: $isError) }
}
.alert(isPresented: $isError, content: {
Alert(title: Text("Error"), message: Text("errorText"), dismissButton: .default(Text("OK")))
})
}
}
class演示类{
func模拟(iError:Binding){
DispatchQueue.global(qos:.background).async{
睡眠(1)
DispatchQueue.main.async{
isError.wrappedValue.toggle()文件
}
}
}
}
结构ContentView:View{
让demo=DemoClass()
@国家私有变量isError=false
var body:一些观点{
VStack{
按钮(“Demo”){Demo.simulate(isError:$isError)}
}
.alert(显示:$isError,内容:{
警报(标题:文本(“错误”)、消息:文本(“错误文本”)、解除按钮:。默认值(文本(“确定”))
})
}
}
你会提供你的代码吗?我添加了合理的代码片段。你会提供你的代码吗?我添加了合理的代码片段。