Swift Firebase Delete Post - ios

I need help deleting a post from firebase. I have the post id key and everything and have been trying all the methods and nothing works. I want to delete the the 3rd child in "posts". I have been trying all types of code. The code below doesn't even throw an error. Not sure what to do. I am getting the values by using a indexpath.row tag.
let postID = self.posts[sender.tag].postID
Database.database().reference().child("posts").child(uid!).child(postID).removeValue { error, _ in
if error != nil {
print("error \(error)")
}
}
Testing
I tried this, and this deletes everything under that user...
Database.database().reference().child("posts").child(uid!).queryOrdered(byChild: "postID").queryEqual(toValue: postID).observe(.value, with: { snapshot in
if snapshot.exists() {
snapshot.ref.removeValue()
print(snapshot)
} else {
print("snapshot doesn't exist")
}
})

check the value of the reference you want to delete by
Database.database().reference().child("posts").child(uid!).child(postID).observe(.value, with: { snapshot in
print(snapshot.value)
})
you can also put them together to check if it's happening locally or not
Database.database().reference().child("posts").child(uid!).child(postID).removeValue()
Database.database().reference().child("posts").child(uid!).child(postID).observe(.value, with: { snapshot in
print(snapshot.value)
})
if it's correct you may don't have access to delete node from the database, check database rules tab in the firebase console
as a last resort you may check your connection because if there is slow connection firebase will cache the updates you make until there is a good connection to sync to the cloud

This works.
Database.database().reference().child("posts").child(uid!).queryOrdered(byChild: "postID").queryEqual(toValue: postID).observe(.childAdded, with: { snapshot in
if snapshot.exists() {
snapshot.ref.removeValue()
print(snapshot)
} else {
print("snapshot doesn't exist")
}
})

Related

Query Firebase Database With Swift

I am trying to query an entry in my firebase realtime database with Swift to basically see if an entry exists with the owner = 33206. My current code is not returning what I need, how can I fix this query?
Here is my code:
var promoCodes: DatabaseReference {
return ref.child("PromoCodes")
}
func getIsAffiliate() {
promoCodes.child("owner").queryEqual(toValue: 33206).observeSingleEvent(of: .value) { snapshot in
print("SNAP HERE: \(snapshot)")
AffiliateService.isAffiliate = snapshot == nil
}
}
Output: SNAP HERE: Snap (owner) <null>
The snapshot passed to your code will never be nil. To check if there are matching nodes, you can check snapshot.exists() instead.

Update a particular subchild in firebase realtime database swift 4

The screenshot above is of the database i created. I successfully am able to upload and retreive data through code but i dont know how to update a subchild. For instance if i want to update the subchild user_name how can i acheive this in swift any snippet would be appreciated.
ref.child("USERS").child(email).child("user_name").setValue("new user name"){
(error:Error?, ref:DatabaseReference) in
if let error = error {
//error
} else {
//do stuff
}
}
}
It's simple, you need just call setValue on the child like this:
ref.observeSingleEvent(of: .value, with: { (snapshot) in
self.ref.child("USERS").child(email).child("user_name").setValue("new User Name")
})

How do I validate if a username exists before sign up in Firebase and Swift 3?

I've incorporated a sign-up flow of five view controllers as opposed to one central VC for Firebase sign up.
Normally there would be the problem of data being lost before sign up, but I'm pushing all the entered values via segue programmatically to the final confirmation page and sending the data to Firebase for auth eventually.
My problem lies therein - I want to check if the username exists before signing up. This is imperative for the UX of my app and I can't just do this all one VC.
Here's the code I have for the UsernameViewController:
let rootRef = FIRDatabase.database().reference()
rootRef.queryOrdered(byChild: "users").queryEqual(toValue: self.chooseUsernameTextField.text!)
.observe(FIRDataEventType.value, with: { (snapshot: FIRDataSnapshot!) in
if snapshot.hasChildren() == false {
print("not found")
} else {
print("usr found")
}
});
Here's the code I have for the Firebase Database Security Rules
{
"rules": {
".read": false,
".write": false,
"users": {
".validate": "data.child('username').val() === true",
".read": true
}
}
}
and finally, a screenshot of my Data tree (My Data tree won't let me nest any new users or create a user node without a value for some reason):
Picture of Firebase Data Tree: App Name/Users
I have a nagging suspicion that my data rules and tree are configured properly to match the code, but I'm stuck in a XY problem of not knowing what to do for Firebase security to get my code of username checking complete.
Please help me! :(
If there's a user created within the Auth section of Firebase as well, then you can actually use the fetchProviders method, and if no providers are returned, you have no user in you Auth section.
FIRAuth.auth()?.fetchProviders(forEmail: email, completion: { (providers, error) in
if providers == nil {
// user doesn't exist
} else {
// user does exist
}
})
I have not tested the code but the theory would be to order by username that equals to the username you are looking for. If this snapshot exists you already have a user in the database with that name if it doesn't you do not.
Will run and test code when i have a chance to and update my post.
let rootRef = FIRDatabase.database().reference()
rootRef.child("users").queryOrdered(byChild:"username").queryEqual(toValue: self.chooseUsernameTextField.text!)
.observe(.value, with: { (snapshot) in
if snapshot.exists() == false {
print("not found")
} else {
print("usr found")
}
});
When using Firestore to save users, I did this
Auth.auth().addStateDidChangeListener({ (auth, user) in
if let id = user?.uid{
let userDoc = db.collection("users").document(id)
userDoc.getDocument { (document, error) in
if document == nil{// if user doesn't exist, create one
self.db.collection("users").document(id).setData(userProfile.toDictionary()){ error in
}
}
}
}
})

Query users in Firebase to check if username exists during sign up process [duplicate]

This question already has an answer here:
Swift & Firebase | Checking if a user exists with a username
(1 answer)
Closed 6 years ago.
Question
How do I check if a username already exists during the user sign up process?
I don't know how to query Firebase to determine if a specific value exists.
Background
Firebase structure:
Users
0BBfrF1vVBXXxNxeVMes9MFkYNJ3
name: "SAM"
0oU9sf7CZxaDBx03t87lqTrv9UM2
name: "JACK"
IsXEqXov0obuwl1WOrHhCbfdfEo1
name: "JEREMY"
In the code below:
I attempt to check if value usernameField exists in: users\userID\name
child(userID) doesn't retrieve anything
_
let username = self.usernameField.text
let userRef = ref.child("Users").child(userID).child("name")
userRef.observeEventType(.Value, withBlock: { snapshot in
if snapshot.value!.isEqual(username) {
print("snapshot exists")
} else {
print("snapshot doesnt exist")
}
userRef.removeAllObservers()
}, withCancelBlock: { error in
print(error)
})
There is a pretty easy way on doing this.
Since you are using removeAllObservers right after the the first callback I'm assuming that you might take a look on using observeSingleEventOfType and you wont need to turn any observer later.
let username = self.usernameField.text
ref.child("Users").queryOrderedByChild("name").queryEqualToValue(username).observeSingleEventOfType(.Value, withBlock: { (snapshot) in
if snapshot.exists == true {
print("snapshot exists")
} else {
print("snapshot doesnt exist")
}
}) { (error) in
print(error.localizedDescription)
}
You should also write some database rules to guarantee the data consistency and performance in the server side. From the current structure you have this wont be straight-forward since you don't have the username as the key for your Users branch.
So I can see two possible solutions:
Username as the key
Saving the username as the /Users key you will just have a rule to enforce this key uniqueness.
{ "rules": {
"Users": {
".indexOn":
".write": "true",
"$username": {
".validate": "!root.child('Users').hasChild($username)"
}
}
}}
This would need some changes on your application code to see if this already exists
ref.child("Users").child(username).observeSingleEventOfType(.Value, withBlock: { (snapshot) in
if snapshot.exists == true {
print("snapshot exists")
} else {
print("snapshot doesnt exist")
}
}) { (error) in
print(error.localizedDescription)
}
Create a new branch to handle the username uniqueness
You want to keep the same structure you have today you will need to do some other changes. Just like the question that Frank linked you will need an extra branch only to store all the taken usernames. So whenever saving a new user you will need to first store the username in this other branch.
{ "rules": {
"Users": {
".indexOn": "name",
".write": "true",
"$id": {
".validate": "!root.child('already_taken_names').hasChild(newData.child('name').val())"
}
},
"already_taken_names": {
"$username": {
".validate": "!root.child('Users').hasChild($username)"
}
}
}}

PFQuery always return same results even though Parse server changed

I'm developing an iOS project using Parse.com as backend server.
Basically, I'm currently implementing a very basic feature which just simply retrieve some objects with simple condition.
However, the objects can only be correctly retrieved the first time. No matter how I changed any values in Parse "Core" via Web, I still cannot get updated values by refreshing in the app.
For example, I have a class called "Event", the fields are changed from Parse server, but the result I retrieve are never updated.
let eventServerQuery = Event.query()
// I tried to clear all cached results
PFQuery.clearAllCachedResults()
eventServerQuery?.whereKey(EventFields.Campus.rawValue, equalTo: campus!)
eventServerQuery?.findObjectsInBackgroundWithBlock({ (allEvents, error) -> Void in
self.refreshControl?.endRefreshing()
self.toggleRefreshButtonWithSpinner(false)
if error != nil {
print(error?.localizedDescription)
}else{
if allEvents?.count > 0 {
// Display on the map
for eventObject in allEvents! {
let event = Event.initializeFieldsFromPFObject(eventObject)
self.delegate?.addEventToMap(event)
self.events.append(event)
print("\(event.updatedAt)")
print("\(event.title) has \(event.numberOfTasks) tasks")
}
// Event TVC data source
self.tableView.reloadData()
}
}
})
If I delete the app in my device and run the project again, it will of course reload everything from scratch, so that the data will become correct again...
Any help will be appreciated!
Finally, I worked out by myself. I found that whenever the PFObject was pinned, its fields will not be updated. The solution is that the object need to be unpinned before retrieve from server.
Event.unpinAllInBackground(events, block: { (success, error) -> Void in
if error != nil {
print(error?.localizedDescription)
}else{
self.events.removeAll()
let eventServerQuery = Event.query()
eventServerQuery?.whereKey(EventFields.Campus.rawValue, equalTo: self.campus!)
eventServerQuery?.findObjectsInBackgroundWithBlock({ (allEvents, error) -> Void in
print("Debug: retrieving events from server")
self.refreshControl?.endRefreshing()
self.toggleRefreshButtonWithSpinner(false)
if error != nil {
print(error?.localizedDescription)
}else{
if allEvents?.count > 0 {
// Display on the map
for eventOnline in allEvents! {
let event: Event = eventOnline as! Event
event.pinInBackground()
self.delegate?.addEventToMap(event)
self.events.append(event)
}
// Event TVC data source
self.tableView.reloadData()
}
}
})
}
})
Welcome to add comments here regarding the internal logic of Parse library, as sometimes it is not quite clear I think.

Resources