2017-08-18 1 views
0

Wenn sich ein Benutzer in der App anmeldet, werden einige Firebase-Beobachtungen, wie z. B. fetchSavedActionsForTracking() und fetchActionsForDowns() (siehe die folgenden vollständigen Funktionen), nicht beobachtet Klicken Sie auf Schaltflächen, und die App verhält sich seltsam, als würde sie sich mit Knoten in Firebase vermischen. Sobald ich den Code erneut kompiliere, funktioniert der Code perfekt und alles kehrt normal zurück. Ich bin mir nicht sicher, ob Xcode dieses Problem verursacht oder ob ich viele Beobachtungen in View Controller habe. Wenn jemand das gleiche Problem hat oder eine Idee hat, lass es mich wissen. Ich habe auch einige Beobachtungen in anderen VC, aber sie sind feinFirebase-Problem mit Beobachtung Sobald sich ein Benutzer angemeldet/angemeldet hat iOS

Hier werden die Beobachtungen ist, ich habe Ich bin View Controller:

func fetchProperties() { 

    // Added the first property 
    Database.database().reference().child("Properties").observe(.childAdded, with: { (snapshot) in 

     if let dictinaryProperty = snapshot.value as? [String: AnyObject]{ 

      // Assign property to Property() 
      self.property = Property() 

      // set the variables in dictionaryProperty's value to property's value (Be carefull the names have to match) 
      self.property?.setValuesForKeys(dictinaryProperty) 

      // User ID in Firebase 
      self.property?.keyID = snapshot.key 

      // Then add it to arrayPropertys 
      self.arrayPropertys.append(self.property!) 

      // This will crash because of background thread, so lets use DispatchQueue.main.async 
      DispatchQueue.main.async(execute: { 
       self.tableView.reloadData() 
      }) 
     } 

    }, withCancel: nil) 


    // Remove 
    Database.database().reference().child("Properties").observe(.childRemoved, with: { (snapshot) in 

     if let dictinaryProperty = snapshot.value as? [String: AnyObject]{ 

      // Assign property to Property() 
      self.property = Property() 

      // set the variables in dictionaryProperty's value to property's value (Be carefull the names have to match) 
      self.property?.setValuesForKeys(dictinaryProperty) 

      // User ID in Firebase 
      self.property?.keyID = snapshot.key 

      // Check on the loaded tracking 
      if self.arrayPropertysTracking.isEmpty != true { 

       // Then delete from Firebase 
       self.checkingAndDeletingTracking(remove: self.property!) 
      } 

      // Then add it to arrayPropertys 
      self.arrayPropertysRemoved.append(self.property!) 

      self.removedProperties() 

      // This will crash because of background thread, so lets use DispatchQueue.main.async 
      DispatchQueue.main.async(execute: { 
       self.tableView.reloadData() 
      }) 
     } 

    }, withCancel: nil) 

    // Child is edited 
    Database.database().reference().child("Properties").observe(.childChanged, with: { (snapshot) in 

     if let dictinaryProperty = snapshot.value as? [String: AnyObject]{ 

      // Assign property to Property() 
      self.property = Property() 

      // set the variables in dictionaryProperty's value to property's value (Be carefull the names have to match) 
      self.property?.setValuesForKeys(dictinaryProperty) 

      // User ID in Firebase 
      self.property?.keyID = snapshot.key 

      // Check if the updated property exists in Tracking window and if it does update it too 
      if self.arrayPropertysTracking.isEmpty != true { 

       self.checkingAndUpdateTracking(update: self.property!) 
      } 

      // Then add it to arrayPropertys 
      self.arrayPropertiesEdited.append(self.property!) 

      self.editedProperties() 

      // This will crash because of background thread, so lets use DispatchQueue.main.async 
      DispatchQueue.main.async(execute: { 
       self.tableView.reloadData() 
      }) 
     } 

    }, withCancel: nil) 


} 

Zweite;

// Load saved actions of the current user 
func fetchSavedActionsForTracking() { 

    let userID = Auth.auth().currentUser?.uid 

    if let actualUserID = userID { 

     // Add the first property 
     Database.database().reference().child("Actions For Tracking").child(actualUserID).observe(.childAdded, with: { (snapshot) in 

      // The key is the property owner's ID 
      let keySnapshot = snapshot.key as? String 

      // Tags of saved buttons 
      let valueSnapshot = snapshot.value as? String 

      if let actualKey = keySnapshot { 

       self.arraySavedKeyIDs.append(actualKey) 

      } 

     //This will crash because of background thread, so lets use DispatchQueue.main.async 
     DispatchQueue.main.async(execute: { 
      self.tableView.reloadData() 
     }) 


     }, withCancel: nil) 

     // Removed the saved actions in Firebase when a property delected in Tracking window 
     Database.database().reference().child("Actions For Tracking").child(actualUserID).observe(.childRemoved, with: { (snapshot) in 

      // The key is the property owner's ID 
      let keySnapshot = snapshot.key as? String 

      // Tags of saved buttons 
      let valueSnapshot = snapshot.value as? String 

      if let actualKey = keySnapshot { 

       self.arrayRemovedTags.append(actualKey) 

      } 

      // Remove the tag from the array 
      self.removedArrayTags() 

      // When saved is clicked twice clear the arrayRemovedTags 
      self.arrayRemovedTags.removeAll() 

      //This will crash because of background thread, so lets use DispatchQueue.main.async 
      DispatchQueue.main.async(execute: { 
       self.tableView.reloadData() 
      }) 

     }, withCancel: nil) 

    } 

} 

Dritte;

// Load properties from tracking window 
func fetchTracking() { 

    let userID = Auth.auth().currentUser?.uid 

    if let actualUserID = userID { 

     Database.database().reference().child("Tracking").child(actualUserID).observe(.childAdded, with: { (snapshot) in 

      if let dictinaryProperty = snapshot.value as? [String: AnyObject]{ 

       // Assign property to Property() 
       self.property = Property() 

       // set the variables in dictionaryProperty's value to property's value (Be carefull the names have to match) 
       self.property?.setValuesForKeys(dictinaryProperty) 

       // Then add it to arrayPropertys 
       self.arrayPropertysTracking.append(self.property!) 

       // This will crash because of background thread, so lets use DispatchQueue.main.async 
       DispatchQueue.main.async(execute: { 
        self.tableView.reloadData() 
       }) 

      } 

     }, withCancel: nil) 

     // Remove 
     Database.database().reference().child("Tracking").child(actualUserID).observe(.childRemoved, with: { (snapshot) in 

      if let dictinaryProperty = snapshot.value as? [String: AnyObject]{ 

       // Assign property to Property() 
       self.property = Property() 

       // set the variables in dictionaryProperty's value to property's value (Be carefull the names have to match) 
       self.property?.setValuesForKeys(dictinaryProperty) 


       // Then add it to arrayPropertys 
       //self.arrayRemovedTracking.append(self.property!) 

       // Remove the property from arrayPropertysTracking 
       for remove in 0...self.arrayPropertysTracking.count-1 { 

        if self.arrayPropertysTracking[remove].keyID == self.property?.keyID { 

         self.arrayPropertysTracking.remove(at: remove) 

         return 

        } 
       } 

       // This will crash because of background thread, so lets use DispatchQueue.main.async 
       DispatchQueue.main.async(execute: { 
        self.tableView.reloadData() 
       }) 
      } 

     }, withCancel: nil) 
    } 
} 

Forth:

// Fetch the down button actions 
func fetchActionsForDowns() { 

    let userID = Auth.auth().currentUser?.uid 

    if let actualUserID = userID { 

     // Add the first property 
     Database.database().reference().child("Actions For Downs").child(actualUserID).observe(.childAdded, with: { (snapshot) in 

      // The key is the property owner's ID 
      let keySnapshot = snapshot.key as? String 

      // Tags of saved buttons 
      let valueSnapshot = snapshot.value as? String 

      if let actualKey = keySnapshot { 

       self.arrayDownsKeyIDs.append(actualKey) 

      } 

      //This will crash because of background thread, so lets use DispatchQueue.main.async 
      DispatchQueue.main.async(execute: { 
       self.tableView.reloadData() 
      }) 


     }, withCancel: nil) 

     // Removed the saved actions in Firebase when a property delected in Tracking window 
     Database.database().reference().child("Actions For Downs").child(actualUserID).observe(.childRemoved, with: { (snapshot) in 

      // The key is the property owner's ID 
      let keySnapshot = snapshot.key as? String 

      // Tags of saved buttons 
      // let valueSnapshot = snapshot.value as? String 

      if let actualKey = keySnapshot { 

       self.arrayDownsRemoved.append(actualKey) 

      } 

      // Remove the action from the array 
      self.removeActionsForDownsFunctions() 

      // When saved is clicked twice clear the arrayRemovedTags 
      self.arrayDownsRemoved.removeAll() 

      //This will crash because of background thread, so lets use DispatchQueue.main.async 
      DispatchQueue.main.async(execute: { 
       self.tableView.reloadData() 
      }) 

     }, withCancel: nil) 

    } 

} 

Fünfte;

func fetchAnsweresOnDowns() { 

    let userID = Auth.auth().currentUser?.uid 
    if let actualUserID = userID { 

     Database.database().reference().child("Answers for Downs").child(actualUserID).observe(.childAdded, with: { (snapshot) in 

      if let dictinaryProperty = snapshot.value as? [String: AnyObject]{ 

       // this will empty the variables in downedProperty 
       self.answerDowns = Property() 

       // set the variables in dictionaryProperty's value to property's value (Be carefull the names have to match) 
       self.answerDowns?.setValuesForKeys(dictinaryProperty) 

       // Type 
       self.answerDowns?.downID = snapshot.key 

       // Then add it to arrayPropertys 
       self.arrayAnswerDowns.append(self.answerDowns!) 

       // Do not upload unless cell has been clicked 
       if self.isExpanded == true { 

        // Upload into received downs 
        self.uploadeReceivedDowns(receive:self.arrayPropertys[(self.selectedIndex?.row)!]) 
       } 


       // This will crash because of background thread, so lets use DispatchQueue.main.async 
       DispatchQueue.main.async(execute: { 
        self.tableView.reloadData() 
       }) 

      } 

     }, withCancel: nil) 

     // Removed property from answers on downs 
     Database.database().reference().child("Answers for Downs").child(actualUserID).observe(.childRemoved, with: { (snapshot) in 

      if let dictinaryProperty = snapshot.value as? [String: AnyObject]{ 

       // this will empty the variables in downedProperty 
       self.answerDowns = Property() 

       // set the variables in dictionaryProperty's value to property's value (Be carefull the names have to match) 
       self.answerDowns?.setValuesForKeys(dictinaryProperty) 

       // Type 
       self.answerDowns?.downID = snapshot.key 

       // Then add it to arrayPropertys 
       self.arrayRemovedAnswerDowns.append(self.answerDowns!) 

       self.removeAnswerDownsFunction() 

       // This will crash because of background thread, so lets use DispatchQueue.main.async 
       DispatchQueue.main.async(execute: { 
        self.tableView.reloadData() 
       }) 

      } 

     }, withCancel: nil) 

    } 


} 

Hier ist die viewDidLoad() Funktion für die Hauptansicht-Controller:

verride func viewDidLoad() { 
    super.viewDidLoad() 
    // Do any additional setup after loading the view, typically from a nib. 


    // User is not logged in 
    checkIfUserIsLogedin() 

    // The delegate for receiving an action/data and notifying the viewcontroller 
    // The datasource is to feed an object such as a tableview and piker from the viewcontroller 
    tableView.delegate = self  // Notify the ViewController whenever the user tabs on rows or scroll 
    tableView.dataSource = self // The dataSource will ask the ViewController for table cells 

    // Initialize ref 
    ref = Database.database().reference() 


    // Creates UINib documents(i.e it create the the files created by main.storyboard or simailiar and truning them to a file) 
    let nib = UINib.init(nibName: "CustomTableViewCell", bundle: nil) 
    tableView.register(nib, forCellReuseIdentifier: "cell") 


    // Set up the search bar 
    searchBarSetup() 

    // This function has to be here to reload table view with added property (i.e refresh table) 

    fetchProperties() 

    fetchSavedActionsForTracking() 

    fetchTracking() 

    fetchActionsForDowns() 

    fetchAnsweresOnDowns() 

} 

und hier ist, wo ich überprüfen, ob der Benutzer angemeldet ist oder nicht ist (existiert auch in den Hauptansicht-Controller):

func checkIfUserIsLogedin() { 
    if Auth.auth().currentUser?.uid == nil { 
     perform(#selector(handleLogout), with: nil, afterDelay: 0) 
     //handleLogout() 
    } 
} 

func handleLogout() { 

    // When User click logout 
    do { 

     try Auth.auth().signOut() 

    } catch let logoutError { 
     print(logoutError) 
    } 

    // Object of loginViewController 

    loginVC = storyboard?.instantiateViewController(withIdentifier: "LoginVC") 

    // Transition to loginViewController() 
    present(loginVC!, animated: true, completion: nil) 

} 

Hier ist die Authentifizierung (I es in separaten view-Controller haben)

Anmelden:

// Sign in into Firebase 
func handleLogin() { 

    // Unwrap the text fields using guard which will simply do if-statament 
    guard let email = emailTextField.text, let password = passwordTextField.text else { 
     print("is nil") 
     return 
    } 

    Auth.auth().signIn(withEmail: email, password: password) { (user, err) in 

     if err != nil { 
      // There is an error 
      if email == "" || password == "" { 

       print("Empty") 
       // Create an alert message 
       let alertMessage = UIAlertController(title: "Empty Fields", message: "Please Fill The Fields", preferredStyle: .alert) 

       // Attach an action on alert message 
       alertMessage.addAction(UIAlertAction(title: "OK", style: .default, handler: { (action) in 
        alertMessage.dismiss(animated: true, completion: nil) 
       })) 
       // Display the alert message 
       self.present(alertMessage, animated: true, completion: nil) 

       return 
      } 

      print("Wrong Email or Password") 
      // Create an alert message 
      let alertMessage = UIAlertController(title: "Wrong Email or Password", message: "Please try again", preferredStyle: .alert) 

      // Attach an action on alert message 
      alertMessage.addAction(UIAlertAction(title: "OK", style: .default, handler: { (action) in 
       alertMessage.dismiss(animated: true, completion: nil) 
      })) 
      // Display the alert message 
      self.present(alertMessage, animated: true, completion: nil) 

      return 

     } 
     // Sueccessful 
     self.presentingViewController?.dismiss(animated: true, completion: nil) 
     print("Login sueccessful into Firebase database") 
    } 

} 

Registrierung:

func handleRegister() { 

    // Unwrap the text fields using guard which will simply do if-statament 
    guard let email = emailTextField.text, let password = passwordTextField.text, let name = nameTextField.text else { 
     print("is nil") 
     return 
    } 

    // Upload the user's name and email into authentication 
    Auth.auth().createUser(withEmail: email, password: password) { (user: User?, error) in 

     if error != nil { 
      // Handle the error (i.e notify the user of the error) 
      if email == "" || password == "" || name == "" { 

       print("Empty") 
       // Create an alert message 
       let alertMessage = UIAlertController(title: "Empty Fields", message: "Please Fill The Fields", preferredStyle: .alert) 

       // Attach an action on alert message 
       alertMessage.addAction(UIAlertAction(title: "OK", style: .default, handler: { (action) in 
        alertMessage.dismiss(animated: true, completion: nil) 
       })) 
       // Display the alert message 
       self.present(alertMessage, animated: true, completion: nil) 

       return 
      } 


      else if let errCode = AuthErrorCode(rawValue: error!._code) { 

       switch errCode { 
       case .invalidEmail: 

        print("invalid email") 
        // Create an alert message 
        let alertMessage = UIAlertController(title: "Invalid Email", message: "Please check the entered email address", preferredStyle: .alert) 
        // Attach an action on alert message 
        alertMessage.addAction(UIAlertAction(title: "OK", style: .default, handler: { (action) in 
         alertMessage.dismiss(animated: true, completion: nil) 
        })) 
        // Display the alert message 
        self.present(alertMessage, animated: true, completion: nil) 

       case .emailAlreadyInUse: 

        print("in use") 
        // Create an alert message 
        let alertMessage = UIAlertController(title: "Existed Email", message: "The email existed in our database, login instead of registering", preferredStyle: .alert) 
        // Attach an action on alert message 
        alertMessage.addAction(UIAlertAction(title: "OK", style: .default, handler: { (action) in 
         alertMessage.dismiss(animated: true, completion: nil) 
        })) 
        // Display the alert message 
        self.present(alertMessage, animated: true, completion: nil) 

       case .weakPassword: 

        print("password is weak") 
        // Create an alert message 
        let alertMessage = UIAlertController(title: "Password is weak", message: "Use upper and lower characters along with numbers", preferredStyle: .alert) 
        // Attach an action on alert message 
        alertMessage.addAction(UIAlertAction(title: "OK", style: .default, handler: { (action) in 
         alertMessage.dismiss(animated: true, completion: nil) 
        })) 
        // Display the alert message 
        self.present(alertMessage, animated: true, completion: nil) 

       default: 
        print("Other error!") 
       } 

      } 
     } 

     // Get the user id from Firebase 
     guard let uid = user?.uid else { 
      return 
     } 


     // Successfully authenticated 

     //Upload the name and user's ID into Database 
     let usersReference = self.ref?.child("Users Info").child(uid) 

     let values = ["name": name, "email": email] 
     //self.ref?.child("User1").setValue(values) 

     // Will add valuse without overwriting 
     usersReference?.updateChildValues(values, withCompletionBlock: { (err, ref) in 

      if err != nil { 
       print(err) 
       return 
      } 

      // Transition to home screen 
      self.presentingViewController?.dismiss(animated: true, completion: nil) 
      print("Saved user successfully into Firebase database") 
     }) 
    } 
} 

Hier ist die viewDidLoad() in dem Logging-View-Controller:

override func viewDidLoad() { 
    super.viewDidLoad() 
    // Do any additional setup after loading the view. 

    // initialize the constraints of the white view and stack view 
    containerView.translatesAutoresizingMaskIntoConstraints = false 
    stackView.translatesAutoresizingMaskIntoConstraints = false 
    nameTextField.translatesAutoresizingMaskIntoConstraints = false 
    emailTextField.translatesAutoresizingMaskIntoConstraints = false 
    passwordTextField.translatesAutoresizingMaskIntoConstraints = false 

    // Create a varaible ref for Firebase 
    ref = Database.database().reference() 

    // You have to add the text field delegate if you want to add fuctions when user press/finish typing. For example when "return" key press, hide the keyboard 
    self.nameTextField.delegate = self 
    self.emailTextField.delegate = self 
    self.passwordTextField.delegate = self 
+0

Wann rufen Sie diese Funktionen auf und wann authentifizieren Sie den Benutzer? –

+0

Hey Jen, ich rufe sie an, sobald der Benutzer sich anmeldet. Ich habe einen anderen View-Controller, der den Benutzer auffordert, sich anzumelden. Ich habe gerade die Authentifizierung in den Post hinzugefügt. – Ahmadiah

+0

Danke für die Aktualisierung. Können Sie auch Ihre viewDidLoad und viewDidAppear einschließen, wenn sie Code enthalten? Weil mein erster Gedanke ist, präsentieren Sie die Anmeldung VC über die andere VC nach der ersten geladen, so dass die Listener möglicherweise registriert werden, bevor der Benutzer tatsächlich angemeldet ist. Aber das ist nur eine Vermutung, da ich den Code nicht habe. –

Antwort

0

in viewDidLoad(), der Code überprüft, ob der Benutzer angemeldet ist in, aber ruft dann

fetchProperties() 

fetchSavedActionsForTracking() 

fetchTracking() 

fetchActionsForDowns() 

fetchAnsweresOnDowns() 

ob der Benutzer angemeldet ist oder nicht. Wenn der Benutzer abgemeldet ist, müssen Sie vermutlich eine Taste drücken, die handleLogin() aufruft. Aber diese fünf Funktionen werden nicht erneut aufgerufen, daher werden die Daten nicht aktualisiert, um den aktuellen Benutzer wiederzugeben. Im Wesentlichen wollen Sie sicher, dass diese Funktionen machen aufgerufen werden, nachdem ein Benutzer angemeldet ist Es gibt viele verschiedene Möglichkeiten, wie Sie dies erreichen können, aber zum Beispiel:.

Anruffunktionen, wenn Benutzer beim Laden App

angemeldet
func checkIfUserIsLogedin() { 
    if Auth.auth().currentUser?.uid == nil { 
     perform(#selector(handleLogout), with: nil, afterDelay: 0) 
     //handleLogout() 
    } else { 
     fetchProperties() 

     fetchSavedActionsForTracking() 

     fetchTracking() 

     fetchActionsForDowns() 

     fetchAnsweresOnDowns()   
    } 
} 

Und dann rufen sie Funktionen, wenn Benutzer sich anmeldet, wenn sie ursprünglich nicht in

angemeldet wurden
func handleLogin() { 
    ... 
    ... 
    // Successful 
    fetchProperties() 

    fetchSavedActionsForTracking() 

    fetchTracking() 

    fetchActionsForDowns() 

    fetchAnsweresOnDowns() 

} 
+0

Hey Jen, danke dafür. Es hat nicht funktioniert. Die beiden nicht beobachteten Funktionen sind fetchSavedActionsForTracking() und fetchActionsForDowns(). Sie wollen zuhören, wenn ich auf eine Schaltfläche klicke, die Daten in Firebase hochlädt. – Ahmadiah

0

Nach einem Blick auf view-Controller-Protokollierung ich fand, dass ich das Logging-view-Controller bin entlassen.Was mein Problem löst, ist der Übergang (was ich nicht 100% ig sicher bin.) Ich habe vom Logging-View-Controller zum Tab-View-Controller gewechselt und funktioniert wunderbar!

Ich würde mich über jede Erklärung freuen, warum das Segment dieses Problem löst.

Danke Jen für Ihre Hilfe!

Verwandte Themen