在 Swift + SwiftUI 中处理错误的好习惯

Posted

技术标签:

【中文标题】在 Swift + SwiftUI 中处理错误的好习惯【英文标题】:A good practice to handle errors in Swift + SwiftUI 【发布时间】:2021-12-30 10:56:59 【问题描述】:

我目前正在 Swift Concurrency 中迈出第一步(使用 async/await/actors)。在集成任务中处理的函数时(通过 Swift 并发),我目前正在使用这个概念来处理错误:

Model.swift

public func submit() async 
    self.isSubmitting = true
    defer  self.isSubmitting = false 
    
    do 
        let result = await worker()
     catch 
        self.hasErrorOccurred = true
        self.errorDescription = error.localizedDescription
    

    self.hasSubmittedSuccessfully = true

ContentView.swift

struct ContentView: View 
    @ObservedObject var model: Model
        
    var body: some View 
        VStack 
            Button(action: 
                Task 
                    await model.submit()
                
            )  Text("Submit") 

            if model.hasErrorOccurred 
                Text(model.errorDescription)
            

            if model.hasSubmittedSuccessfully 
                Text("Success")
            
        
    

我想知道这是否是用这种方法处理错误或成功反馈的好习惯。你是怎么处理的?

【问题讨论】:

我正在开发一个小型错误处理框架,该框架将它们向上传递到视图层次结构,直到视图处理它们。今晚我将添加对“Alertable”错误的支持,以及一个在触发错误时自动显示警报的 ViewModifier。你可以在这里找到 WIP github.com/EmilioPelaez/ErrorHierarchy。如果您想进一步讨论,请随时与我联系 :) 【参考方案1】:

所有这些布尔标志都不是一个好习惯。

我的建议是一个带有关联值的枚举

enum WorkResult 
    case none, success(String), failure(Error)

Model 中采用ObservableObject,声明@Published 属性并在submit 方法中分配案例。这将更新视图。这个简单的例子在两秒后返回字符串“Hello”。

@MainActor
class Model : ObservableObject 
    
    @Published var submission : WorkResult = .none
   
    public func submit() async 
        do 
            let result = try await worker()
            submission = .success(result)
         catch 
            submission = .failure(error)
        

    
    
    func worker() async throws -> String 
        try await Task.sleep(nanoseconds: 2_000_000_000)
        return "Hello"
    

在视图switch上枚举并处理案例

struct ContentView : View 
    @StateObject private var model = Model()
    
    var body: some View 
        VStack 
            Button(action: 
                Task 
                    await model.submit()
                
            )  Text("Submit") 
            switch model.submission 
                case .success(let result): Text(result)
                case .failure(let error): Text(error.localizedDescription)
                default: EmptyView()
            
        
        
        
    

【讨论】:

非常好的提议!

以上是关于在 Swift + SwiftUI 中处理错误的好习惯的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Swift UIKit Map 组件中处理 SwiftUI 中的触摸手势?

SwiftUI - 发出获取请求时收到错误

Swift / SwiftUI:如何检查环境 /binding var 是不是为空字符串(.isEmpty 出现构建错误)

如何使用 Swift 完成处理程序的结果?

将核心数据从 Swift 迁移到 SwiftUI

Swift UI:当视图中显示空列表时,如何显示错误消息?