ios SwiftUI -在多个视图中触发错误弹出窗口

wz3gfoph  于 2023-03-31  发布在  iOS
关注(0)|答案(2)|浏览(234)

我试图在我的项目中使用MV架构,下面是我的代码的一个简单示例:

struct PaymentView: View {
    @StateObject private var store = PaymentStore()
    
    var body: some View {
        NavigationStack {
            PaymentCreditorListView()
            /* -> PaymentFormView() */
            /* -> PaymentUnpaidView() */
            /* -> PaymentConfirmationView() */
        }
        .environmentObject(store)
    }
}

class PaymentStore: ObservableObject {
     ....
    @Published var isLoading = false
    @Published var popup: Popup?
    
    private let service: PaymentService
    
    init(service: PaymentService = PaymentService()) {
        self.service = service
    }
    
    func getPaymentCreditors() async {
        do {
            isLoading = true
            let response = try await service.fetchPaymentCreditors()
            .....
            isLoading = false
        } catch {
            isLoading = false
            popup = .init(error: error)
        }
    }
    
    func getPaymentForm() async {
        do {
            isLoading = true
            let response = try await service.fetchPaymentForm()
            ....
            isLoading = false
        } catch {
            isLoading = false
            popup = .init(error: error)
        }
    }
    
    func getPaymentUnpaid() async {
        do {
            isLoading = true
            let response = try await service.fetchPaymentUnpaid()
            .....
            isLoading = false
        } catch {
            isLoading = false
            popup = .init(error: error)
        }
    }
}

在每个视图上,我使用工作表来显示弹出错误,因为有时我需要为该视图做一些特定的事情(例如:调用Web服务或重定向等)

.sheet(item: $store.popup) { popup in
    PopupView(popup: popup) 
}

我现在遇到的唯一问题是,当其中一个端点返回错误时,所有使用弹出窗口的视图都被触发,并且我在控制台中收到此警告消息***“尝试在已经呈现的 * 上呈现 ...”**,progressLoader也有同样的问题,它将触发所有其他视图。
我是否错过了这种方法的一些东西?或者有更好的方法来做到这一点?

ars1skjm

ars1skjm1#

您可以为每个View创建一个@State
从删除开始

@Published var popup: Popup?

并添加到您的View

@State private var popup: Popup?

然后在函数中,你需要类似于

func getPaymentCreditors(popup: Binding<Popup?>) async {
    do {
        isLoading = true
        let response = try await service.fetchPaymentCreditors()
        .....
        isLoading = false
    } catch {
        isLoading = false
        popup.wrappedValue = .init(error: error)
    }
}

工作表将引用局部变量

.sheet(item: $popup) { popup in
7jmck4yq

7jmck4yq2#

这是因为你同时调用了这三个API,并且显示了所有三个API的错误。你需要检查是否已经显示了错误

if popup != nil {
   popup = .init(error: error)
}

当然,如果你没有任何其他代码试图显示某些内容,这取决于你如何使用getPaymentCreditors()和其他方法。当popup更新时,PaymentStore更新所有内部视图,因为你将其用作环境对象。然而,如果不使用子视图中的任何更新字段(例如弹出窗口)当你不应该担心-一个子视图将更新在这种情况下更新UI。它将更新UI只有当子视图依赖于更新的字段。

相关问题