美文网首页
Swift 用async改造delegate

Swift 用async改造delegate

作者: Auditore | 来源:发表于2024-05-10 15:56 被阅读0次

    Swift Async改造delegate

    1.背景

    Async await的组合是Swift异步编程的核心,它让原本难以读懂的delegate异步过程,变得更加可读。但直接使用Async和await是不够的,我们需要引入withCheckedContinuation{} 这个函数

    2.范例

    假如我有一个函数,调用以后,它通过delegate异步返回结果。这是一个非常典型的异步函数调用过程。那我们要怎么用Swift的async-await改造它呢?

    我们先看看原来长什么样,如下面代码所示,是一个很常见的异步请求回调的过程。

    import Foundation
    
    protocol RequestDelegate: AnyObject {
        func onLoadedList(_ status: RequestStatus)
    }
    
    enum RequestStatus {
        case success
        case fail
    }
    
    class TestDataHanlder {        
        func fetchListData(_ delegate: RequestDelegate) {
            // call a method with delegate
            loadListData(delegate)
        }
        
        func loadListData(_ delegate: RequestDelegate) {
            // do something needs time...
        }    
    }
    
    extension TestDataHanlder: RequestDelegate {
        func onLoadedList(_ status: RequestStatus) {
            // request done, update UI or something else..
        }                                                        
    }
    

    让我们用async和withCheckedContinuation来改造一下,我们声明了一个CheckedContinuation,把它定义为CheckedContinuation<RequestStatus, Never>,就是告诉系统,返回值是RequestStatus,错误类型是Never。

    接着,我们把fetchListData函数改成了async异步函数,在内部,return await withCheckedContinuation,返回值就是loadContinuation的返回值,也就是我们定义好的RequestStatus类型。

    最后我们要做的是,是在delegate方法中,调用loadContinuation?.resume(returning: status),并且把delegate返回的status往上抛出。

    这样一个delegate的async改造就好了

    import Foundation
    
    protocol RequestDelegate: AnyObject {
        func onLoadedList(_ status: RequestStatus)
    }
    
    enum RequestStatus {
        case success
        case fail
    }
    
    class TestDataHanlder {
        typealias TestContinuation = CheckedContinuation<RequestStatus, Never>
        private var loadContinuation: TestContinuation?
            
        func fetchListData(_ delegate: RequestDelegate) async -> RequestStatus {
            return await withCheckedContinuation { continuation in
                loadContinuation = continuation
                self.loadListData(delegate)
            }
        }
        
        func loadListData(_ delegate: RequestDelegate) {
            // do something needs time...
        }    
    }
    
    extension TestDataHanlder: RequestDelegate {
        func onLoadedList(_ status: RequestStatus) {
            loadContinuation?.resume(returning: status)
            // !!! WARNING: you must clear the loadContinuation after resume
            loadContinuation = nil
        }                                                        
    }
    

    需要注意,当你在异步回调delegate方法里resume之后,要把CheckedContinuation置为nil,否则会有难以预料的结果。

    相关文章

      网友评论

          本文标题:Swift 用async改造delegate

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