2017-03-29 2 views
2

私は本当にスレッディングに慣れていて、終日読んでいます。何らかの理由で他のコードが実行される前にデータがロードされていないのですが私のfirebaseデータベースが値の更新を待たずにいる理由

基本的に私は配列に書き込むキーを持つすべての値を必要とします。最初にロードする必要があります。だから私はチェックして、私が更新しているキーが存在し、私が抽出しているキーは多分まだ値が存在しないが、キーが行うことを確認します。

問題はコードがメソッドを高速化することです。どのように私は私のfirebaseそれまでは、メインスレッドの待ち時間が、私は以下のことを試してみましたデータをロードしていますが、それはここで

を動作していないようになるだろうと、私のコードは、以下の関数が値を更新し

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { 
    let alertController = UIAlertController(title: "Accept Bet", message: "Match the bet of " + amountBets[indexPath.row], preferredStyle: .alert) 

    let okButton = UIAlertAction(title: "No", style: .default, handler: { (action) -> Void in 
     print("Ok button tapped") 
    }) 

    let yesButton = UIAlertAction(title: "Yes", style: .default, handler: { (action) -> Void in 
     // let them know to wait a second or the bet won't go through 
     var waitController = UIAlertController(title: "Please Wait", message: "You must wait for the bet to go through", preferredStyle: .alert) 

     self.present(waitController, animated: true, completion: nil) 
     //take away that bitches money 
     self.takeAwayMoney(self.amountBets[indexPath.row], completion: { (result: Bool?) in 

      guard let boolResult = result else { 
       return 
      } 

      if boolResult == true { 
       self.updateBet(indexPath.row, completion: {(result: String?) in 





        guard let resultRecieved = result else { 
         return 
        } 
        print(self.opposingUserNames) 
        //let delayInSeconds = 7.0 // 1 
        //DispatchQueue.main.asyncAfter(deadline: .now() + delayInSeconds) { // 2 
        self.dismiss(animated: true, completion: nil) 
        let successController = UIAlertController(title: "Success", message: "You have made a bet with " + self.opposingUserNames!, preferredStyle: .alert) 
        let okButt = UIAlertAction(title: "Ok", style: .default, handler: nil) 
        successController.addAction(okButt) 
        self.present(successController, animated: true, completion: nil) 
        //lastly delete the opposing UserName 
        print(self.opposingUserNames) 
        self.amountBets.remove(at: indexPath.row) 
        self.tableView.reloadData() 
        print("Second") 
        print(self.opposingUserNames) 
        //} 

       }) 
      } else { 
       return 
      } 

     }) 

     //then delete that cell and do another pop up that says successful 
     // check if value is yes or no in the database 


    }) 

    alertController.addAction(okButton) 
    alertController.addAction(yesButton) 
    present(alertController, animated: true, completion: nil) 
} 

あるOpposingUsernameそれは私が以前持っていた論理エラーを切り出して、今アプリは私のwaitAlertViewControllerにハングアップし、この更新されたコードを持つように

func updateBet(_ index: Int, completion: @escaping (_ something: String?) -> Void) { 
    let userID = FIRAuth.auth()?.currentUser?.uid 
    datRef.child("User").child(userID!).observeSingleEvent(of: .value, with: { (snapshot) in 
     // Get user value 
     let value = snapshot.value as? NSDictionary 
     // ... 


     self.datRef.child("Bets").observe(.childAdded, with: { snapshot in 
      // 
      // this is the unique identifier of the bet. eg, -Kfx81GvUxoHpmmMwJ9P 
      guard let dict = snapshot.value as? [String: AnyHashable] else { 
       print("failed to get dictionary from Bets.\(self.userName)") 
       return 
      } 
      let values = ["OpposingUsername": self.userName,"Show": "no"] 


      self.datRef.child("Bets").child(self.tieBetToUser[index]).updateChildValues(values) 
      // now get the opposing username which is just the Username registered to that specific bet 
      self.datRef.child("Bets").child(self.tieBetToUser[index]).observe(.childAdded, with: { snapshot in 
       guard let dict2 = snapshot.value as? [String: AnyHashable] else { 
        return 
       } 
       let userNameOfOtherPlayer = dict2["Username"] as? String 
       self.opposingUserNames = userNameOfOtherPlayer! 
       completion(self.opposingUserNames) 
      }) 


     }) 

    }) { (error) in 
     print(error.localizedDescription) 
    } 


} 

OKを示しています。理由は分かりません。それはfirebaseデータベースのベットを更新しているので、私はそのコードを実行していることを知っていますが、そのコードを実行することは決して完全ではありません。申し訳ありませんbibscy私はあなたがそれを呼び出すとき、それはすぐに返すことを意味し、asyncronous関数であるあなたが

完了ハンドラは、あなたがより良い

+0

ObserveSingleEvent(OF_)それらを理解すれば、かなり強力で、今何を意味するかを見、それはありません中括弧内のコードを実行しないで、バックグラウンドスレッドで作業を続け、実行が終了すると、結果は 'completion:@escaping(_ result')になります。現在の設定では、完了ハンドラが呼び出されますあなたが 'didSelectRowAt indexPath'で' getOpoosingUserNames'を呼び出すときには、self.updateBet(indexPath.row、completion:{(result:String)in)と文字列( "success" 'の後に' – bibscy

+0

あなたはあなたが望む結果を得ることができ、現在は' opposingUserNames'を保持します。その後、tableViewをリロードすることができます。もしあなたがそれを働かせたら教えてください。 – bibscy

+1

私の答えは[Firebase is asynchronous](http://stackoverflow.com/questions/37104816/finish-asynchronous-task-in-firebase-with-swift/37124220#37124220)をご覧ください。クロージャ内のコードが実行される前に、クロージャの外側のコード*が実行されます。 Firebase関数から返されたデータを処理する場合は、クロージャ内で*行う必要があります。 – Jay

答えて

2
//Notice that I made `result: String?` optional, it may or may not have a value.  
func getOpoosingUserNames(_ username: String,_ index: Int, completion: @escaping (_ result: String?) -> Void) { 
    let userID = FIRAuth.auth()?.currentUser?.uid 
    datRef.child("User").child(userID!).observeSingleEvent(of: .value, with: { (snapshot) in 
     // Get user value 
     let value = snapshot.value as? NSDictionary 
     let username = value?["username"] as? String ?? "" 
     self.userName = username 

     // ... 


     self.datRef.child("Bets").observe(.childAdded, with: { snapshot in 
      // 
      // this is the unique identifier of the bet. eg, -Kfx81GvUxoHpmmMwJ9P 

      let betId = snapshot.key as String 
      guard let dict = snapshot.value as? [String: AnyHashable] else { 
       print("failed to get dictionary from Bets.\(self.userName)") 
       return 
      } 
      if let show = dict["Show"] as? String { 

       let opposingUser = dict["OpposingUsername"] as? String 
        self.opposingUserNames.append(opposingUser!) 
      } 



      completion(opposingUserNames) 
     }) 
    }) { (error) in 
     print(error.localizedDescription) 
    } 

} 



    //update the be 
    func updateBet(_ index: Int, completion: @escaping (_ something: [String]?) -> Void) { 
    let userID = FIRAuth.auth()?.currentUser?.uid 
datRef.child("User").child(userID!).observeSingleEvent(of: .value, with: { (snapshot) in 
    // Get user value 
    let value = snapshot.value as? NSDictionary 
    // ... 


    self.datRef.child("Bets").observe(.childAdded, with: { snapshot in 
     // 
     // this is the unique identifier of the bet. eg, -Kfx81GvUxoHpmmMwJ9P 
     guard let dict = snapshot.value as? [String: AnyHashable] else { 
      print("failed to get dictionary from Bets.\(self.userName)") 
      return 
     } 
     let values = ["OpposingUsername": self.userName,"Show": "no"] 

    //store the values received from Firebase in let valueOfUpdate and pass this 
    // constant to your completion handler completion(valueOfUpdate) so that you can use this value in func 
    //tableView(_ tableView:_, didSelectRowAt indexPath:_) 
      let valueOfUpdate = self.datRef.child("Bets").child(self.tieBetToUser[index]).updateChildValues(values) 



    completion(valueOfUpdate) 
    }) { (error) in 
    print(error.localizedDescription) 
    } 


} 


    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { 
    let alertController = UIAlertController(title: "Accept Bet", message: "Match the bet of " + amountBets[indexPath.row], preferredStyle: .alert) 

    let okButton = UIAlertAction(title: "No", style: .default, handler: { (action) -> Void in 
     print("Ok button tapped") 
    }) 

    let yesButton = UIAlertAction(title: "Yes", style: .default, handler: { (action) -> Void in 
     //take away that bitches money 
     self.takeAwayMoney(self.amountBets[indexPath.row]) 

     //then delete that cell and do another pop up that says successful 
     // check if value is yes or no in the database 
     self.updateBet(indexPath.row, completion: {(result: String) in 


    guard let resultReceivedInupdateBet = result, else { 
    print("result of updateBet() is \(result)") 
} 
     print("If you see this print, database was updated") 

    //calling this method with the indexPath.row clicked by the user 
    self.getOpoosingUserNames(self.userName, indexPath.row, completion: { (result: [String]) in 


guard let resultReceivedIngetOpoosingUserNames = result{ 
     print("result of getOpoosingUserNames is \(result)") 
} 
    print("If you see this print, you received a value from db after calling getOpoosingUserNames and that value is in \(result) ") 

    //result is not nil, resultReceivedIngetOpoosingUserNames has the same value as result. 

}//end of self.getOpoosingUserNames 

     self.checkForNo(indexPath.row) 
     self.amountBets.remove(at: indexPath.row) 
     self.tableView.reloadData() 
     print(self.opposingUserNames) 

     let successController = UIAlertController(title: "Success", message: "You have made a bet with " + self.opposingUserNames[indexPath.row], preferredStyle: .alert) 
     let okButt = UIAlertAction(title: "Ok", style: .default, handler: nil) 
     successController.addAction(okButt) 
     self.present(successController, animated: true, completion: nil) 
     //lastly delete the opposing UserName 
     self.opposingUserNames.remove(at: indexPath.row) 

    }) 

    alertController.addAction(okButton) 
    alertController.addAction(yesButton) 
    present(alertController, animated: true, completion: nil) 
} 
+0

私はあなたの助けを借りてコードを更新しました。私はまだエラーを受けています。コードはまだバックグラウンドで実行されていて、他のコードを実行中です。 –

+0

私は、メインスレッドまでself.opposingUserNames配列に値があります –

+0

@DevinTripp私は自分の答えを更新しました。今動作していない場合は、あなたが言ったように、あなたのコードのロジックに何か間違いがあります。したがって、行が選択されたとき1。updateBet()が呼び出されました。データが受信されなかった場合は、結果で受け取ったデータをチェックし、ステートメントと終了関数を出力します。 2データが受信された場合は、選択された行のindexPath.rowを使用してgetOpoosingUserNamesを呼び出します。次に、getOpoosingUserNamesの結果がnilか実際に値を取得したかどうかを確認するためにguardを再度使用します。 – bibscy

関連する問題