美文网首页
Swift网络访问改为async方式 2023-05-11 周四

Swift网络访问改为async方式 2023-05-11 周四

作者: 勇往直前888 | 来源:发表于2023-05-10 18:55 被阅读0次

简介

网络库已经封装了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

相关文章

网友评论

      本文标题:Swift网络访问改为async方式 2023-05-11 周四

      本文链接:https://www.haomeiwen.com/subject/zbtjsdtx.html