Swift 并发 UIButton

Swift Concurrency UIButton

是否可以在 UIKit 中对 POST HTTP 请求使用 async/await,即来自 UIButton 的请求?

我可以收到发送的请求,但它立即崩溃了。使用 URLSession 完美工作,以此作为学习经验。

lazy var buttonTest: UIButton = {
    let button = UIButton()
    button.addTarget(self, action: #selector(testAsyncTwo), for: .touchUpInside)
    return button
}()

@objc func testAsync() async throws {
    let date = Date()
    let df = DateFormatter()
    df.dateFormat = "yyyy-MM-dd HH:mm:ss"
    let dateString = df.string(from: date)

    let json: [String: Any] = ["item": "1",
                               "time": "\(dateString)"]
    let jsonData = try? JSONSerialization.data(withJSONObject: json)
    
    guard let url = URL(string: "https://myapiendpoint.com/api/") else { fatalError("Missing URL") }
    var urlRequest = URLRequest(url: url)
    let token: String = "mySecretKey"
    urlRequest.setValue("Token \(token)", forHTTPHeaderField: "Authorization")
    urlRequest.httpMethod = "POST"
    urlRequest.setValue("\(String(describing: jsonData?.count))", forHTTPHeaderField: "Content-Length")
    urlRequest.setValue("application/json", forHTTPHeaderField: "Content-Type")
    urlRequest.httpBody = jsonData
    let (data, response) = try await URLSession.shared.data(for: urlRequest)
    
    guard (response as? HTTPURLResponse)?.statusCode == 200 else { fatalError("Error while fetching data") }
    let responseJSON = try? JSONSerialization.jsonObject(with: data, options: [])
    if let responseJSON = responseJSON as? [String: Any] {
        print(responseJSON) //Code after Successfull POST Request
    }
}

非常感谢!

崩溃与您的 URLSession 代码无关。问题是您已将按钮的选择器声明为异步抛出函数。这与 @objc 选择器不兼容。

替换:

@objc func testAsync() async throws { 
    ... 
}

与:

@objc func didTapButton(_ sender: Any) {
    Task {
        try await testAsync()
    }
}

func testAsync() async throws {
    ...
}

主要观察结果是 @objc 方法不是异步函数。我还会给按钮处理程序一个 sender 参数和一个更具描述性的名称,以遵循既定的约定并一目了然地表明它正在处理按钮点击。

显然,执行此操作时,您还必须更改 #selector 引用:

button.addTarget(self, action: #selector(didTapButton(_:)), for: .touchUpInside)