使 UI 等待方法响应

Make UI Wait for Method Response

我是一名新 swift 开发人员。我正在使用 Swift 4.2 和 Xcode 10.2.

我需要 UI 等待方法完成,以便我可以使用结果显示余额。我试图为此使用 dispatchGroup,但它似乎没有等待,因为下面 user?.userId 的值是 nil。这是我的代码:

    // Load the local user data.  Must wait until this is done to continue.
    let dispatchGroup = DispatchGroup()

    dispatchGroup.enter()
    let user = LocalStorageService.loadCurrentUser()
    dispatchGroup.leave()

    // Display the current balance.
    // Get a reference to the Firestore database.
    let db = Firestore.firestore()

    // Make sure we have a userId and then update the balance with a listener that keeps it updated.
    // Only run this part when the dispatchGroup has completed (in this case, the user is loaded).
    dispatchGroup.notify(queue: .main) {
        if let userId = user?.userId {

            db.collection("subs").whereField("ID", isEqualTo: userId)
                .addSnapshotListener { querySnapshot, error in
                    // Make sure we have a document
                    guard let document = querySnapshot?.documents.first else {
                        print("Error fetching document: \(error!)")
                        return
                    }
                    // We have a document and it has data.  Use it.
                    self.balance = document.get("balance") as! Double

                    // Format the balance
                    let currencyFormatter = NumberFormatter()
                    currencyFormatter.numberStyle = .currency
                    let balanceString = currencyFormatter.string(from: self.balance as NSNumber)
                    self.balanceLabel.setTitle(balanceString, for: .normal)
            }
        }
    }

如何让 UI 等待 dispatchGroup.enter() 中调用的方法完成?

这是 LoadCurrentUser 中的内容....

static func loadCurrentUser() -> User? {

    // Loads the current user in the UserDefaults if there is one

    let defaults = UserDefaults.standard

    let userId = defaults.value(forKey: Constants.LocalStorage.storedUserId) as? String
    let phoneNumber = defaults.value(forKey: Constants.LocalStorage.storedPhoneNumber) as? String
    let subscriberId = defaults.value(forKey: Constants.LocalStorage.storedDocumentId) as? String

    guard userId != nil && phoneNumber != nil && subscriberId != nil else {
        return nil
    }

    // Return the user
    let u = User(userId:userId!, phoneNumber:phoneNumber!, subscriberId: subscriberId)

    return u
}

目前,您通过在回调中设置 vars 来正确执行此操作,因此不需要 DispatchGroup,但要正确使用它然后执行(请注意每行应按 1 到 4 之间的数字排列的正确位置)

let dispatchGroup = DispatchGroup() /// 1

let user = LocalStorageService.loadCurrentUser()

// Display the current balance.
// Get a reference to the Firestore database.
let db = Firestore.firestore()
var balance = ""
// Make sure we have a userId and then update the balance with a listener that keeps it updated.
// Only run this part when the dispatchGroup has completed (in this case, the user is loaded).

    if let userId = user?.userId {

         dispatchGroup.enter() /// 2

        db.collection("subs").whereField("ID", isEqualTo: userId)
            .addSnapshotListener { querySnapshot, error in
                // Make sure we have a document
                guard let document = querySnapshot?.documents.first else {
                    print("Error fetching document: \(error!)")
                    return
                }
                // We have a document and it has data.  Use it.
                self.balance = document.get("balance") as! Double 

                  dispatchGroup.leave() /// 3

        }
    }

  dispatchGroup.notify(queue: .main) { /// 4
      //update here 
     // Format the balance
       let currencyFormatter = NumberFormatter()
       currencyFormatter.numberStyle = .currency 
       let balanceString = currencyFormatter.string(from: self.balance as NSNumber)
      self.balanceLabel.setTitle(balanceString, for: .normal)
  }