Completion Handler 调用 N 次

Completion Handler Call N times

在Button动作中,我调用了getLatLongValues方法,它会在API成功后return完成属性。

听说问题是,如果我在按钮操作中单击 N 次,getLatLongValues 方法将执行 N 次。
就像我第一次点击按钮 getLatLongValues 执行 1 次,我点击第二次而不是两次 getLatLongValues 方法执行 2 次。

@IBAction func updateDeliveryAddress() {
    guard let address = self.addressTextField.text else { return }
    self.getLatLongValues(address, true, viewModel) { success in
        if success {
            //Success
        } else {
            // Error
        }
    }
}

func getLatLongValues(address: String, setAsDefault: Bool, viewModel:ViewModel, completion: @escaping (_ success: Bool) -> Void) {
    viewModel.location.subscribe(onNext: { [weak self] results in
        guard self != nil else { return }
        if let result = results {
                completion(true) // Success
        }
    }).disposed(by: disposeBag)
    viewModel.fetchLocation(address: address)
}

为什么getLatLongValues执行N次?

因为每次您都在创建新订阅。 订阅不是执行一次的完成处理程序。

viewModel.location.subscribe(onNext: { [weak self] results in

应该只调用一次,并且在每次位置更新时,您都会在块中得到结果

如果你希望完成处理程序只被调用一次,你应该设置一个标志:

var completionHandlerExecuted = false /// false at first

func getLatLongValues(address: String, setAsDefault: Bool, viewModel:ViewModel, completion: @escaping (_ success: Bool) -> Void) {
    
    if completionHandlerExecuted == false {
        completionHandlerExecuted = true /// set to true, so it won't be called again


        viewModel.location.subscribe(onNext: { [weak self] results in
            guard self != nil else { return }
            if let result = results {
                completion(true) // Success
            }
        }).disposed(by: disposeBag)
        viewModel.fetchLocation(address: address)
    }

}

完成处理程序与您放入函数中的任何其他指令一样。

每次调用 getLatLongValues 时,您都在执行 subscribe,它会在完成后调用完成处理程序。