3

我正在尝试基于计算属性在 Swift 中显示警报。基本上,每当用户单击按钮时,“round”的值都会更新。当进行超过 10 轮时,会显示警报。

为此,我创建了一个名为“showingAlert”的布尔变量。这必须是一个 @State 变量,以便在用户关闭警报时再次设置为 false。

但是,编译器告诉我像@State 这样的属性包装器“不能应用于计算属性”:-(

这是我尝试过的代码:


@State var round = 0
@State var showingAlert:Bool {round > 10 ? true : false}

func result(player: Int, app: Int) {
if player > app {
 round += 1
 }
else {
 round += 1
}
}

var body: some View {
        Button(action: {self.result(player: 1, app: 1)}) {
        Text("Button")
        }
           .alert(isPresented: $showingAlert) {
                Alert(title: Text("title"), message: Text("message"), dismissButton: .default(Text("Continue"))
                )
} 

有没有办法解决这个问题?我很想创建一个不显示错误消息的警报。

4

2 回答 2

3

我更喜欢将逻辑放入模型中——将逻辑与视图分离——但这里有一些可行的方法:

@State var round = 0
@State var showingAlert:Bool = false

func result(player: Int, app: Int) {
    if player > app {
        round += 1
    } else {
        round += 1
    }
    if round > 10 {
        showingAlert.toggle()
    }
}

基本上,将您的支票转移到您的功能中。笔记:

  • 我假设这是测试逻辑......如果不是,你有一个错字,if/else因为他们都做同样的事情。
  • 仅设置showingAlert为 true - 让 SwiftUI 在解除警报时将其设置为 false。
  • 将这个逻辑从视图中分离出来的真正原因是你可以让事情很容易重置 round。这是执行此操作的代码:
import SwiftUI
import Combine

class Model : ObservableObject {
    var objectWillChange = PassthroughSubject<Void, Never>()
    @Published var showingAlert = false {
        willSet {
            objectWillChange.send()
            if newValue == false {
                round = 0
            }
        }
    }
    var round = 0
    func result(player: Int, app: Int) {
        if player > app {
            round += 1
        } else {
            round += 1
        }
        if round > 10 {
            showingAlert.toggle()
        }
    }
}

struct ContentView: View {
    @EnvironmentObject var model: Model

    var body: some View {
        Button(action: {self.model.result(player: 1, app: 1)}) {
            Text("Button")
            }
        .alert(isPresented: self.$model.showingAlert) {
                Alert(title: Text("title"), message: Text("message"), dismissButton: .default(Text("Continue")))
            }
    }
}

请注意,只有一个变量 ( showingAlert) 标记为@Published,您可以对其进行正确编码willSet,而您需要更改的只是正确ContentView添加 EnvironmentObject after your add it to yourSceneDelegate`。

第一组代码将在第 11 次点击后显示警报,然后每次点击。第二组代码将在第 11 次点击后显示警报,之后每 11 次点击。

于 2019-10-27T13:31:11.043 回答
3

您可以简单地使用Binding.constant(_:)。将计算属性转换为绑定属性。


@State var round = 0
var showingAlert:Bool {round > 10 ? true : false}

func result(player: Int, app: Int) {
  if player > app {
   round += 1
   }
  else {
   round += 1
  }
}

var body: some View {
        Button(action: {self.result(player: 1, app: 1)}) {
        Text("Button")
        }
           .alert(isPresented: .constant(showingAlert)) {
                Alert(title: Text("title"), message: Text("message"), dismissButton: .default(Text("Continue"))
                )
} 
于 2020-02-28T21:51:45.447 回答