英文:
SwiftUI - Showing and hiding a custom alert
问题
我正在创建一个自定义警报可重用修饰符,其按钮数量取决于我需要的样式。无论如何,在下面的示例代码中,我已经尽量删除了尽可能多的额外代码,以保持其简洁和简单。
在下面的代码中,我能够显示警报,但单击“Click Me”按钮无法关闭警报。我觉得我在设置“isPresented”绑定变量时出了问题,但无法弄清楚是什么问题。我是 SwiftUI 的新手。
自定义警报修饰符:
struct CustomAlertView: ViewModifier {
var isPresented: Binding<Bool>
init(isPresented: Binding<Bool>) {
self.isPresented = isPresented
}
func body(content: Content) -> some View {
content.overlay(alertContent())
}
@ViewBuilder
private func alertContent() -> some View {
GeometryReader { geometry in
if self.isPresented.wrappedValue {
// 做一些操作
// 单击按钮时将 isPresented 设置为 false 时没有起作用。
Button(action: { self.isPresented.wrappedValue = false }) {
Text("Click Me")
}
}
}
}
}
func customAlert(isPresented: Binding<Bool>) -> some View {
return modifier(CustomAlertView(isPresented: isPresented))
}
视图和视图模型代码:
struct MyView: View {
@ObservedObject var viewModel: CustomViewModel = CustomViewModel()
var body: some View {
VStack {
switch viewModel.state {
case .idle:
Color.clear.onAppear(perform: { viewModel.doSomething() })
case .showNewView:
// 导航
}
}.onAppear() {
viewModel.state = .idle
}.customAlert(isPresented: .constant(viewModel.showAlert))
}
}
@MainActor
class CustomViewModel: ObservableObject {
enum State {
case idle
case showNewView
}
@Published var state = State.idle
@Published var showAlert = false
func doSomething() {
if failure {
self.showAlert = true
} else {
self.state = .showNewView
}
}
}
我看不出你的代码有明显的错误。在你的代码中,你使用了 isPresented
绑定来显示和关闭警报。可能问题出在其他地方,比如 failure
的值。确保 failure
的值是正确的,当它为 true
时,self.showAlert
被设置为 true
。如果问题仍然存在,请提供更多代码上下文以便更好地理解和解决问题。
英文:
I am creating a custom alert reusable modifier which will have different number of buttons depending upon the style I need. Anyways in my sample code below, I have removed as much extra code as I can to keep it small and simple.
With the code below, I am able to show the alert, but clicking on "Click Me" button does not dismiss the alert. I feel something is wrong with the way I am setting "isPresented" binding variable, but not able to figure out what. Am new to SwiftUI.
Custom Alert Modifier:
struct CustomAlertView: ViewModifier {
var isPresented: Binding<Bool>
init(isPresented: Binding<Bool>) {
self.isPresented = isPresented
}
func body(content: Content) -> some View {
content.overlay(alertContent())
}
@ViewBuilder
private func alertContent() -> some View {
GeometryReader { geometry in
if self.isPresented {
// Do something
// Setting isPresented to false is not doing anything when button is clicked.
Button(action: { self.isPresented.wrappedValue = false }) {
Text("Click Me")
}
}
}
}
}
func customAlert(isPresented: Binding<Bool>) -> some View {
return modifier(CustomAlertView(isPresented: isPresented))
}
View and view model code:
struct MyView: View {
@ObservedObject var viewModel: CustomViewModel = CustomViewModel()
var body: some View {
VStack {
switch viewModel.state {
case .idle:
Color.clear.onAppear(perform: { viewModel.doSomething() })
case .showNewView:
// Navigate
}
}.onAppear() {
viewModel.state = .idle
}.customAlert(isPresented: .constant(viewModel.showAlert))
}
}
@MainActor
class CustomViewModel: ObservableObject {
enum State {
case idle
case showNewView
}
@Published var state = State.idle
@Published var showAlert = false
func doSomething() {
if failure {
self.showAlert = true
} else {
self.state = .showNewView
}
}
}
What am I doing wrong or why am I not able to dismiss the alert?
Thanks for looking!
答案1
得分: 2
首先,您需要在CustomAlertView
内部使用@Binding var isPresented: Bool
,并在init
中将其分配为self._isPresented = isPresented
:
struct CustomAlertView: ViewModifier {
@Binding var isPresented: Bool // <-- 类似于这样
init(isPresented: Binding<Bool>) {
self._isPresented = isPresented // <-- 以及这样
}
//...
其次,您绝对不希望在.customAlert(isPresented: .constant(viewModel.showAlert))
中将isPresented
设置为常量。相反,您需要传递绑定变量:
VStack {
// ...
}
.customAlert(isPresented: $viewModel.showAlert) // <-- 在这里绑定它
英文:
First of all, you want @Binding var isPresented: Bool
inside the CustomAlertView
, and you assign it in init
as self._isPresented = isPresented
:
struct CustomAlertView: ViewModifier {
@Binding var isPresented: Bool // <-- like this
init(isPresented: Binding<Bool>) {
self._isPresented = isPresented // <-- and like this
}
//...
And second, you definitely don't want to set isPresented
to a constant in .customAlert(isPresented: .constant(viewModel.showAlert))
. Instead, you need to pass the binding variable:
VStack {
// ...
}
.customAlert(isPresented: $viewModel.showAlert) // <-- bind it here
</details>
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论