swift - Firebase Issue with Observation Once a user sign in/up iOS -
whenever user signs in/up app, firebase observations, such fetchsavedactionsfortracking() , fetchactionsfordowns() (see full functions below), not observe during clicking buttons , app acts weird mixing nodes in firebase. compile code again, code works perfect , returns normal. not sure if xcode causes issue or have many observations in view controller. if experience same problem or have idea, please let me know. have couple of observations in other vc fine
here observations have i'm view controller:
func fetchproperties() { // added first property database.database().reference().child("properties").observe(.childadded, with: { (snapshot) in if let dictinaryproperty = snapshot.value as? [string: anyobject]{ // assign property property() self.property = property() // set variables in dictionaryproperty's value property's value (be carefull names have match) self.property?.setvaluesforkeys(dictinaryproperty) // user id in firebase self.property?.keyid = snapshot.key // add arraypropertys self.arraypropertys.append(self.property!) // crash because of background thread, 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 property() self.property = property() // set variables in dictionaryproperty's value property's value (be carefull names have match) self.property?.setvaluesforkeys(dictinaryproperty) // user id in firebase self.property?.keyid = snapshot.key // check on loaded tracking if self.arraypropertystracking.isempty != true { // delete firebase self.checkinganddeletingtracking(remove: self.property!) } // add arraypropertys self.arraypropertysremoved.append(self.property!) self.removedproperties() // crash because of background thread, lets use dispatchqueue.main.async dispatchqueue.main.async(execute: { self.tableview.reloaddata() }) } }, withcancel: nil) // child edited database.database().reference().child("properties").observe(.childchanged, with: { (snapshot) in if let dictinaryproperty = snapshot.value as? [string: anyobject]{ // assign property property() self.property = property() // set variables in dictionaryproperty's value property's value (be carefull names have match) self.property?.setvaluesforkeys(dictinaryproperty) // user id in firebase self.property?.keyid = snapshot.key // check if updated property exists in tracking window , if update if self.arraypropertystracking.isempty != true { self.checkingandupdatetracking(update: self.property!) } // add arraypropertys self.arraypropertiesedited.append(self.property!) self.editedproperties() // crash because of background thread, lets use dispatchqueue.main.async dispatchqueue.main.async(execute: { self.tableview.reloaddata() }) } }, withcancel: nil) } second;
// load saved actions of current user func fetchsavedactionsfortracking() { let userid = auth.auth().currentuser?.uid if let actualuserid = userid { // add first property database.database().reference().child("actions tracking").child(actualuserid).observe(.childadded, with: { (snapshot) in // key 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 crash because of background thread, lets use dispatchqueue.main.async dispatchqueue.main.async(execute: { self.tableview.reloaddata() }) }, withcancel: nil) // removed saved actions in firebase when property delected in tracking window database.database().reference().child("actions tracking").child(actualuserid).observe(.childremoved, with: { (snapshot) in // key 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 tag array self.removedarraytags() // when saved clicked twice clear arrayremovedtags self.arrayremovedtags.removeall() //this crash because of background thread, lets use dispatchqueue.main.async dispatchqueue.main.async(execute: { self.tableview.reloaddata() }) }, withcancel: nil) } } third;
// load properties 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 property() self.property = property() // set variables in dictionaryproperty's value property's value (be carefull names have match) self.property?.setvaluesforkeys(dictinaryproperty) // add arraypropertys self.arraypropertystracking.append(self.property!) // crash because of background thread, 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 property() self.property = property() // set variables in dictionaryproperty's value property's value (be carefull names have match) self.property?.setvaluesforkeys(dictinaryproperty) // add arraypropertys //self.arrayremovedtracking.append(self.property!) // remove property arraypropertystracking remove in 0...self.arraypropertystracking.count-1 { if self.arraypropertystracking[remove].keyid == self.property?.keyid { self.arraypropertystracking.remove(at: remove) return } } // crash because of background thread, lets use dispatchqueue.main.async dispatchqueue.main.async(execute: { self.tableview.reloaddata() }) } }, withcancel: nil) } } forth:
// fetch down button actions func fetchactionsfordowns() { let userid = auth.auth().currentuser?.uid if let actualuserid = userid { // add first property database.database().reference().child("actions downs").child(actualuserid).observe(.childadded, with: { (snapshot) in // key 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 crash because of background thread, lets use dispatchqueue.main.async dispatchqueue.main.async(execute: { self.tableview.reloaddata() }) }, withcancel: nil) // removed saved actions in firebase when property delected in tracking window database.database().reference().child("actions downs").child(actualuserid).observe(.childremoved, with: { (snapshot) in // key 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 action array self.removeactionsfordownsfunctions() // when saved clicked twice clear arrayremovedtags self.arraydownsremoved.removeall() //this crash because of background thread, lets use dispatchqueue.main.async dispatchqueue.main.async(execute: { self.tableview.reloaddata() }) }, withcancel: nil) } } fifth;
func fetchansweresondowns() { let userid = auth.auth().currentuser?.uid if let actualuserid = userid { database.database().reference().child("answers downs").child(actualuserid).observe(.childadded, with: { (snapshot) in if let dictinaryproperty = snapshot.value as? [string: anyobject]{ // empty variables in downedproperty self.answerdowns = property() // set variables in dictionaryproperty's value property's value (be carefull names have match) self.answerdowns?.setvaluesforkeys(dictinaryproperty) // type self.answerdowns?.downid = snapshot.key // add arraypropertys self.arrayanswerdowns.append(self.answerdowns!) // not upload unless cell has been clicked if self.isexpanded == true { // upload received downs self.uploadereceiveddowns(receive:self.arraypropertys[(self.selectedindex?.row)!]) } // crash because of background thread, lets use dispatchqueue.main.async dispatchqueue.main.async(execute: { self.tableview.reloaddata() }) } }, withcancel: nil) // removed property answers on downs database.database().reference().child("answers downs").child(actualuserid).observe(.childremoved, with: { (snapshot) in if let dictinaryproperty = snapshot.value as? [string: anyobject]{ // empty variables in downedproperty self.answerdowns = property() // set variables in dictionaryproperty's value property's value (be carefull names have match) self.answerdowns?.setvaluesforkeys(dictinaryproperty) // type self.answerdowns?.downid = snapshot.key // add arraypropertys self.arrayremovedanswerdowns.append(self.answerdowns!) self.removeanswerdownsfunction() // crash because of background thread, lets use dispatchqueue.main.async dispatchqueue.main.async(execute: { self.tableview.reloaddata() }) } }, withcancel: nil) } } here viewdidload() function main view controller:
verride func viewdidload() { super.viewdidload() // additional setup after loading view, typically nib. // user not logged in checkifuserislogedin() // delegate receiving action/data , notifying viewcontroller // datasource feed object such tableview , piker viewcontroller tableview.delegate = self // notify viewcontroller whenever user tabs on rows or scroll tableview.datasource = self // datasource ask viewcontroller table cells // initialize ref ref = database.database().reference() // creates uinib documents(i.e create the files created main.storyboard or simailiar , truning them file) let nib = uinib.init(nibname: "customtableviewcell", bundle: nil) tableview.register(nib, forcellreuseidentifier: "cell") // set search bar searchbarsetup() // function has here reload table view added property (i.e refresh table) fetchproperties() fetchsavedactionsfortracking() fetchtracking() fetchactionsfordowns() fetchansweresondowns() } and here check if user logged in or not (also exists in main view controller):
func checkifuserislogedin() { if auth.auth().currentuser?.uid == nil { perform(#selector(handlelogout), with: nil, afterdelay: 0) //handlelogout() } } func handlelogout() { // when user click logout { try auth.auth().signout() } catch let logouterror { print(logouterror) } // object of loginviewcontroller loginvc = storyboard?.instantiateviewcontroller(withidentifier: "loginvc") // transition loginviewcontroller() present(loginvc!, animated: true, completion: nil) } here authentication (i have in separate view controller)
sign in:
// sign in firebase func handlelogin() { // unwrap text fields using guard 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 error if email == "" || password == "" { print("empty") // create alert message let alertmessage = uialertcontroller(title: "empty fields", message: "please fill fields", preferredstyle: .alert) // attach action on alert message alertmessage.addaction(uialertaction(title: "ok", style: .default, handler: { (action) in alertmessage.dismiss(animated: true, completion: nil) })) // display alert message self.present(alertmessage, animated: true, completion: nil) return } print("wrong email or password") // create alert message let alertmessage = uialertcontroller(title: "wrong email or password", message: "please try again", preferredstyle: .alert) // attach action on alert message alertmessage.addaction(uialertaction(title: "ok", style: .default, handler: { (action) in alertmessage.dismiss(animated: true, completion: nil) })) // display alert message self.present(alertmessage, animated: true, completion: nil) return } // sueccessful self.presentingviewcontroller?.dismiss(animated: true, completion: nil) print("login sueccessful firebase database") } } registering:
func handleregister() { // unwrap text fields using guard if-statament guard let email = emailtextfield.text, let password = passwordtextfield.text, let name = nametextfield.text else { print("is nil") return } // upload user's name , email authentication auth.auth().createuser(withemail: email, password: password) { (user: user?, error) in if error != nil { // handle error (i.e notify user of error) if email == "" || password == "" || name == "" { print("empty") // create alert message let alertmessage = uialertcontroller(title: "empty fields", message: "please fill fields", preferredstyle: .alert) // attach action on alert message alertmessage.addaction(uialertaction(title: "ok", style: .default, handler: { (action) in alertmessage.dismiss(animated: true, completion: nil) })) // display 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 alert message let alertmessage = uialertcontroller(title: "invalid email", message: "please check entered email address", preferredstyle: .alert) // attach action on alert message alertmessage.addaction(uialertaction(title: "ok", style: .default, handler: { (action) in alertmessage.dismiss(animated: true, completion: nil) })) // display alert message self.present(alertmessage, animated: true, completion: nil) case .emailalreadyinuse: print("in use") // create alert message let alertmessage = uialertcontroller(title: "existed email", message: "the email existed in our database, login instead of registering", preferredstyle: .alert) // attach action on alert message alertmessage.addaction(uialertaction(title: "ok", style: .default, handler: { (action) in alertmessage.dismiss(animated: true, completion: nil) })) // display alert message self.present(alertmessage, animated: true, completion: nil) case .weakpassword: print("password weak") // create alert message let alertmessage = uialertcontroller(title: "password weak", message: "use upper , lower characters along numbers", preferredstyle: .alert) // attach action on alert message alertmessage.addaction(uialertaction(title: "ok", style: .default, handler: { (action) in alertmessage.dismiss(animated: true, completion: nil) })) // display alert message self.present(alertmessage, animated: true, completion: nil) default: print("other error!") } } } // user id firebase guard let uid = user?.uid else { return } // authenticated //upload name , user's id database let usersreference = self.ref?.child("users info").child(uid) let values = ["name": name, "email": email] //self.ref?.child("user1").setvalue(values) // add valuse without overwriting usersreference?.updatechildvalues(values, withcompletionblock: { (err, ref) in if err != nil { print(err) return } // transition home screen self.presentingviewcontroller?.dismiss(animated: true, completion: nil) print("saved user firebase database") }) } } here viewdidload() in logging view controller:
override func viewdidload() { super.viewdidload() // additional setup after loading view. // initialize constraints of white view , stack view containerview.translatesautoresizingmaskintoconstraints = false stackview.translatesautoresizingmaskintoconstraints = false nametextfield.translatesautoresizingmaskintoconstraints = false emailtextfield.translatesautoresizingmaskintoconstraints = false passwordtextfield.translatesautoresizingmaskintoconstraints = false // create varaible ref firebase ref = database.database().reference() // have add text field delegate if want add fuctions when user press/finish typing. example when "return" key press, hide keyboard self.nametextfield.delegate = self self.emailtextfield.delegate = self self.passwordtextfield.delegate = self
in viewdidload(), code checks if user logged in, calls
fetchproperties() fetchsavedactionsfortracking() fetchtracking() fetchactionsfordowns() fetchansweresondowns() whether or not user logged in. if user logged out, presumably need press button calls handlelogin(). doesn't call 5 functions again, data isn't updated reflect current user. essentially, want make sure functions called after user logged in. there lots of different ways achieve this, example:
call functions if user logged in upon loading app
func checkifuserislogedin() { if auth.auth().currentuser?.uid == nil { perform(#selector(handlelogout), with: nil, afterdelay: 0) //handlelogout() } else { fetchproperties() fetchsavedactionsfortracking() fetchtracking() fetchactionsfordowns() fetchansweresondowns() } } and call functions when user logs in if weren't logged in
func handlelogin() { ... ... // successful fetchproperties() fetchsavedactionsfortracking() fetchtracking() fetchactionsfordowns() fetchansweresondowns() }
Comments
Post a Comment