在Swift中,回调和完成处理程序之间的区别是什么?

3
在Combine框架中,我发现以下文本

Combine框架为您的应用程序处理事件提供了一种声明性方法。而不是潜在地实现多个委托回调或完成处理程序

有人能告诉我Swift中完成处理程序和回调之间的区别吗?
(注:Original Answer翻译成“最初的回答”)
5个回答

4

代理回调是当您预先知道一个委托实现了一个方法(例如,它采用了一个协议),您通过名称调用该方法。

完成处理程序是当有人将一个函数交给您,您只需通过引用盲目地调用它。


2

明确一点,实际上你可以通过两种方式实现相同的功能,但设计应用程序的方法完全不同。

让我用一个简单的例子来澄清两者之间在执行相同函数(进行网络调用)时的区别。

  • 代理协议

最初的回答:

要清楚,实际上您可以使用两种方法实现相同的功能,但是设计应用程序的方法完全不同。让我用一个简单的例子来澄清两者之间在执行相同函数(进行网络调用)时的区别。

代理协议

    // enum to define the request type

enum RequestTypes {

    case UserRegister
    case UserLogin

}


protocol ServiceDelegate {

    func didCompleteRequest(responseModel: AnyObject, tag: RequestTypes)

}

// you can also add default impl to the methods here

extension ServiceDelegate {

    func didCompleteRequest(responseModel: AnyObject, tag: RequestTypes){}

}



class BaseService<ResponseModel: Codable> {

    var session: URLSession!
    var delegate: ServiceDelegate?

    // MARK: Rebuilt Methods
    func FireRequest(){

        // Request Preparation
        let serviceUrl = URL(string: /* your url */)!
        var request = URLRequest(url: serviceUrl)
        request.httpMethod = "GET"


        // Firing the request
        session = URLSession.init(configuration: URLSessionConfiguration.default)
        session.dataTask(with: request) { (data, response, error) in
            if let data = data {
                do {
                    guard let object = try? JSONDecoder().decode(ResponseModel.self , from: data) else {/* handle error or call delegate error method here */ return }
                    delegate?.didCompleteRequest(responseModel: object, tag: .UserLogin)
                }
            }
            }.resume()
    }

}




class ViewController: UIViewController, ServiceDelegate {

    override func viewDidLoad() {
        super.viewDidLoad()
        fetchNewData()
    }

    func fetchNewData(){
        let service = BaseService<YourModel>()
        service.delegate = self
        service.FireRequest()
    }

    func didCompleteRequest(responseModel: AnyObject, tag: RequestTypes) {
        if tag == /* the tag you are waiting */ .UserLogin {
            // YourModel is available here
        }
    }


}

  • 完成处理程序

class BaseService<ResponseModel: Codable> {

    var session: URLSession!

    // MARK: Rebuilt Methods

    func FireRequest(completion: ((ResponseModel?) -> Void)?){

        // Request Preparation
        let serviceUrl = URL(string: /* your url */)!
        var request = URLRequest(url: serviceUrl)
        request.httpMethod = "GET"


        // Firing the request
        session = URLSession.init(configuration: URLSessionConfiguration.default)
        session.dataTask(with: request) { (data, response, error) in
            if let data = data {
                do {
                    guard let object = try? JSONDecoder().decode(ResponseModel.self , from: data) else {/* handle error or call delegate error method here */ return }
                    DispatchQueue.main.async {
                        completion?(object)
                    }
                }
            }
            }.resume()
    }

}


class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        fetchNewData()
    }

    func fetchNewData(){

        let service = BaseService<YourModel>()

        service.FireRequest(completion: { [weak self] (response) in
            // yourModel Available here once the request completed
        })

    }

}

1

回调是一种在特定情况下向其他函数发送数据的方式。Swift中有两种实现回调的方法。

  1. 使用协议/代理
  2. 使用完成处理程序

使用协议/代理示例:

声明协议

protocol MyDelegate {
     public method(param: String);
}

您的ViewController应该扩展委托

class YourViewController: MyDelegate {
     // Your Other methods

     func method(param: String) {
      // Do your stuff
     }
 }

现在,在您的其他类中,您可以通过委托对象向ViewController发送回调,例如:

delegate.method(param: "your_param");

使用完成处理程序的示例:
public func method(param: String, completionHandler: @escaping (_ param: String) -> Void)
{
    ...
    // now you can send data back to the caller function using completionHandler on some particular occasion 
     completionHandler("param");
}

我们可以像这样调用这个函数:
method(param: String, completionHandler: { (result, alreadyUserId) in
      // here you will receive callback
});

你明白了吗?如果有任何进一步的问题,请告诉我。 - Asad Ali Choudhry

1
一个委托回调是各种视图控制器和类之间的一对一通信。它基本上让您知道特定视图或任何其他地方已经进行了特定更改,现在您可以在此操作后进行更改。
完成处理程序是在完成特定过程或任务后执行的块。

0
回调函数和完成处理程序在异步方法中是同义词。
我发现主要的区别在于它们在定义返回给调用者的内容时的使用方式。当涉及到将作用域返回给前一个调用方法时,使用回调函数;而当涉及到将某种“结果”类型返回给调用者时,则使用完成处理程序。

这是不正确的。例如URLSession使用代理,并且它所称之为的不是完成处理程序,而是代理回调。 - matt

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接