Заставить интерфейс ждать ответа метода - PullRequest
0 голосов
/ 24 июня 2019

Я новый быстрый разработчик. Я использую Swift 4.2 и Xcode 10.2.

Мне нужен мой интерфейс, чтобы дождаться завершения метода, чтобы я мог использовать результат для отображения баланса. Я пытаюсь использовать 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)
            }
        }
    }

Как заставить пользовательский интерфейс ждать завершения метода, вызванного в 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
}

1 Ответ

0 голосов
/ 24 июня 2019

В настоящее время вы делаете это правильно, устанавливая переменные внутри функции обратного вызова, поэтому нет необходимости в 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)
  }
...