You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Swift中如何在View中展示completion handler返回的异步值

解决方案

你需要按照SwiftUI响应式数据流规范改造代码,核心思路是让数据层的变更可以主动通知视图刷新,具体操作如下:

第一步:改造Commands类

让它遵循ObservableObject协议,把需要通知视图更新的属性用@Published修饰:

import Alamofire
import SwiftUI

class Commands: ObservableObject {
    // @Published修饰的属性变更时,会自动给视图发送更新通知
    @Published var status_code: String = "0"
    private let credentials: Credentials // 替换为你实际的Credentials类型
    
    init(credentials: Credentials) {
        self.credentials = credentials
    }
    
    private func send(method: String, path: String, code: Array<Int>, headers: HTTPHeaders, completionHandler: @escaping (Int) -> Void) {
        let url: String = "\(self.credentials.url)/\(path)"

        AF.request(url, method: HTTPMethod(rawValue: method), headers: headers)
            .authenticate(with: self.request_credentials)
            .response { response in
                // 替换强制解包为可选绑定,避免网络异常时闪退
                guard let statusCode = response.response?.statusCode else {
                    // 可自定义异常场景的返回码
                    completionHandler(-1)
                    return
                }
                completionHandler(statusCode)
            }
    }
    
    func list_files(path: String) {
        let headers: HTTPHeaders = [
            "Depth": "1"
        ]
        
        // 加[weak self]避免循环引用
        send(method: "PROPFIND", path: path, code: [207, 301], headers: headers) { [weak self] status_code in
            // 显式指定主线程更新属性,保证UI刷新逻辑安全
            DispatchQueue.main.async {
                self?.status_code = String(status_code)
            }
        }
    }
}

第二步:改造ContentView视图

使用@StateObject持有ObservableObject实例,把网络请求放到onAppear生命周期回调中执行,不要在body的计算过程中初始化实例和发起请求:

struct ContentView: View {
    // @StateObject保证实例在视图生命周期内唯一,不会因为视图重绘被销毁重建
    @StateObject private var commands: Commands
    
    init() {
        let auth = Authentication(
            username: "****",
            domain: "****",
            password: "****",
            port: ****,
            proto: "****",
            path:"****"
        )
        // @StateObject的标准初始化方式
        _commands = StateObject(wrappedValue: Commands(credentials: auth.get_credentials()))
    }
    
    var body: some View {
        Text(commands.status_code)
            .padding()
            .onAppear {
                // 视图渲染完成后发起异步请求
                commands.list_files(path: "/")
            }
    }
}

内容的提问来源于stack exchange,提问作者AdamSwift

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.27 05:06:00