简介
网络库已经封装了Alamofire,只是结果返回是block形式的(也就是闭包),容易形成回调地狱,所以想改为async/await方式。
/// Alamofire 网络信息封装
public class AFNetRequest: NSObject {
// MARK: - Lifecycle
/// 单例实例
/// AFNetRequest.sharedInstance.就是单例的用法
/// AFNetRequest().就是普通实例的用法
public static let sharedInstance = AFNetRequest()
private override init() {}
/// GET、POST网络请求
public func requestData(URLString: String,
type: AFMethodType,
parameters: [String: Any]? = nil,
respondCallback: @escaping (_ responseObject: [String: AnyObject]?, _
error: NSError?) -> Void) {
/// 具体封装过程省略
}
}
基本思路
-
在原有的requestData外面再包一层,将respondCallback用异步的结构代替
-
成功返回结果,错误抛出异常信息,这是最容易想到的一种方式
-
Swift原生提供了withUnsafeThrowingContinuation可以达到这种功能;
也可以用PromiseKit这个第三方库来实现,JS就可以用这种方式来做。JavaScript:async/await的基础用法
function sleep(ms) {
return new Promise((resolve) => {
setTimeout(() => {
resolve('sleep for ' + ms + ' ms');
}, ms);
});
}
- await需要放在async标记的函数中,表示异步过程
/// 网络访问包装为async方式
public func asyncRequestData(URLString: String,
type: AFMethodType,
parameters: [String: Any]?) async throws -> [String: AnyObject]?
{
try await withUnsafeThrowingContinuation { continuation in
requestData(URLString: URLString, type: type, parameters: parameters) { responseObject, error in
if let error = error {
continuation.resume(throwing: error)
} else {
continuation.resume(returning: responseObject)
}
}
}
}
如何使用
-
async/await配套的麻烦:
await需要放在async标记的函数中;而async函数调用的时候需要加await标记,这样互相要求,就会导致要求最外层的比如ViewDidLoad()之类的都要加上async标记才行。 -
Task{}结构可以打破这个async/await配套循环,在没有async的普通函数中调用async标记的异步函数。
func pagerView(_ pagerView: FSPagerView, didSelectItemAt index: Int) {
print("Did select item at \(index)")
let item = banners[index]
let urlString = item["link"] as! String
var idd: String?
if let url = URL(string: urlString), let components = URLComponents(url: url, resolvingAgainstBaseURL: true) {
if let queryItems = components.queryItems {
for item in queryItems {
if item.name == "id" {
idd = item.value
}
}
}
}
let strURL = "https://test.pandabuy.com/gateway/resource/notice/detail"
let parameter: [String: Any] = [
"id": idd as! String,
]
/// 这是直接使用block的例子
// AFNetRequest().requestData(URLString: strURL, type: .get, parameters: parameter) { responseObject, error in
// if error != nil {
// print("Error: \(error?.description ?? "")")
// return
// }
//
// if let _ = responseObject {
// let data = responseObject?["data"]
//
//
// FlutterBoost.instance().open(
// "pandaWeb",
// arguments: ["animated": true, "present": false,"data":data!,"type":0,"title":data!["title"]],
// completion: { _ in }
// )
// }
// }
/// 这是使用Task包async函数的例子
Task {
do {
let response = try await AFNetRequest.sharedInstance.asyncRequestData(URLString: strURL, type: .get, parameters: parameter)
if let data = response?["data"] {
FlutterBoost.instance().open(
"pandaWeb",
arguments: ["animated": true, "present": false, "data": data, "type": 0, "title": data["title"] as Any],
completion: { _ in }
)
}
} catch {
debugPrint(error)
}
}
}
参考文章
将Alamofire完成处理程序转换为Async/Await | Swift5.5
并发
'async' call in a function that does not support concurrency swift ios Xcode async/await
Swift 5.5之Continuation
网友评论