简体   繁体   English

Swift 并发 UIButton

[英]Swift Concurrency UIButton

Is it possible to use async/await for POST HTTP requests in UIKit, namely a from UIButton ?是否可以在 UIKit 中使用 async/await 来处理 POST HTTP 请求,即来自UIButton的请求?

I can get the request sent but then it immediately crashes.我可以发送请求,但它会立即崩溃。 Working perfectly using URLSession , using this as a learning experience.使用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
    }
}

Thanks very much!非常感谢!

The crash is unrelated to your URLSession code.崩溃与您的URLSession代码无关。 The problem is that you have declared the button's selector to be asynchronous throwing function.问题是您已将按钮的选择器声明为异步抛出函数。 That is incompatible with an @objc selector.这与@objc选择器不兼容。

Replace:代替:

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

With:和:

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

func testAsync() async throws {
    ...
}

The key observation is that the @objc method is not an asynchronous function.关键的观察是@objc方法不是一个异步函数。 I would also give the button handler a sender parameter and a more descriptive name, to follow established conventions and make it clear at a glance that it is handling a button tap.我还会给按钮处理程序一个sender参数和一个更具描述性的名称,以遵循既定的约定并一目了然地表明它正在处理按钮点击。

Obviously, when you do this, you will have to change the #selector reference, too:显然,当您这样做时,您也必须更改#selector引用:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM