如何在执行某些操作之前管理多个异步任务?

时间:2018-02-09 23:36:35

标签: ios swift

我是编程初学者。我实际上对这些问题有自己的答案,应用程序按照我的预期工作,但我不确定这是否是正确的方法。

用户点击chechoutButton后会触发此结帐操作。但在此chechoutButton.isEnabled之前,我必须确保有3个参数可用(不是零)。在执行此检查操作之前,我需要3个参数:

  1. 从GPS获取用户坐标。
  2. 从Google Place获取用户的位置地址     API
  3. 从服务器获取当前日期时间以进行验证。
  4. 只有当我从GPS获取坐标时才会触发从Google Place API获取用户位置地址的方法,而且我们知道,从互联网上获取数据(采取日期和时间)也需要时间,应该这样做异步。

    如果这3个参数不是nil,我该如何管理这个checkoutButton?根据苹果指南有没有更好的方法来做到这一点

    简化代码如下

    class CheckoutTVC: UITableViewController {
    
        @IBOutlet weak var checkOutButton: DesignableButton!
    
    
        var checkinAndCheckoutData : [String:Any]? // from MainMenuVC
        var dateTimeNowFromServer : String?
        var userLocationAddress : String?
    
        let locationManager = LocationManager()
    
        var coordinateUser : Coordinate? {
            didSet {
                getLocationAddress()
            }
        }
    
    
    
        override func viewDidLoad() {
            super.viewDidLoad()
    
            // initial state
            checkOutButton.alpha = 0.4
            checkOutButton.isEnabled = false
    
            getDateTimeFromServer()
            getCoordinate()
    
    
    
        }
    
        @IBAction func CheckoutButtonDidPressed(_ sender: Any) {
    
        }
    
    
    
    
    }
    
    
    
    extension CheckoutTVC {
    
    
    
        func getDateTimeFromServer() {
    
            activityIndicator.startAnimating()
            NetworkingService.getDateTimeFromServer { (result) in
    
                switch result {
                case .failure(let error) :
                    self.activityIndicator.stopAnimating()
                    // show alert
    
                case .success(let timeFromServer) :
                    let stringDateTimeServer = timeFromServer as! String
                    self.dateTimeNowFromServer = stringDateTimeServer
    
                    self.activityIndicator.stopAnimating()
                }
            }
    
        }
    
    
        func getCoordinate() {
            locationManager.getPermission()
            locationManager.didGetLocation = { [weak self] userCoordinate in
                self?.coordinateUser = userCoordinate
                self?.activateCheckOutButton()
            }
        }
    
    
    
        func getLocationAddress() {
    
            guard let coordinateTheUser = coordinateUser else {return}
            let latlng = "\(coordinateTheUser.latitude),\(coordinateTheUser.longitude)"
    
            let request = URLRequest(url: url!)
            Alamofire.request(request).responseJSON { (response) in
    
    
                switch response.result {
                case .failure(let error) :// show alert
                case .success(let value) :
                    let json = JSON(value)
                    let locationOfUser = json["results"][0]["formatted_address"].string
                    self.userLocationAddress = locationOfUser
                    self.locationAddressLabel.text = locationOfUser
                    self.activateNextStepButton()
                }
    
    
            }
    
        }
    
    
        func activateCheckoutButton() {
    
            if dateTimeNowFromServer != nil && userLocationAddress != nil {
                checkOutButton.alpha = 1
                checkOutButton.isEnabled = true
            }
    
        }
    
    
    }
    

    我通过使用此方法来管理它,但我不知道这是否是正确的方法

    func activateCheckoutButton() {
    
            if dateTimeNowFromServer != nil && userLocationAddress != nil {
                checkOutButton.alpha = 1
                checkOutButton.isEnabled = true
            }
    
        }
    

1 个答案:

答案 0 :(得分:1)

您可以使用DispatchGroup知道所有异步调用何时完成。

func notifyMeAfter3Calls() {
    let dispatch = DispatchGroup()

    dispatch.enter()
    API.call1() { (data1)
        API.call2(data1) { (data2)
           //DO SOMETHING WITH RESPONSE
           dispatch.leave()
        }
    }

    dispatch.enter()
    API.call3() { (data)
        //DO SOMETHING WITH RESPONSE
        dispatch.leave()
    }

    dispatch.notify(queue: DispatchQueue.main) {
        finished?(dispatchSuccess)
    }
}

您必须拥有相同数量的enter()leave()来电。完成所有leave()调用后,将调用DispatchGroupd.notify中的代码。