This question already has answers here:
Returning data from async call in Swift function
(13 answers)
Closed 3 years ago.
Within my function to load users I'm able to retrieve a value. However, when I want to assign it to my variable outside the function it has nothing, as shown in the login function.
Load User Function
func loadUser(userid: String) -> User {
//print(userid)
let userid = "56ldZFJiv0dpfaABzo78"
var user = User()
let docRef = db.collection("users").document(userid)
docRef.getDocument { (document, error) in
if let document = document {
let first = document.data()!["first"] as! String
let last = document.data()!["last"] as! String
let position = document.data()!["position"] as! String
let company = document.data()!["company"] as! String
let email = document.data()!["email"] as! String
let address = document.data()!["address"] as! String
let userID = document.data()!["userID"] as! String
//Initalize user
user = User(userID: userID,
firstName: first,
lastName: last,
company: company,
address: address,
position: position,
email: email)
print(user.position)
} else {
print("Document does not exist")
}
}
return user
}
Login Function
//MARK: LOGIN
func login() {
Auth.auth().signIn(withEmail: emailField.text!, password: passwordField.text!) { (user, error) in
if error == nil{
//self.performSegue(withIdentifier: "loginToAdmin", sender: self)
//Load user
let loggedOnUser = self.loadUser(userid: Auth.auth().currentUser!.uid)
print(loggedOnUser.userID)
// let storyBoard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
// let chatViewController = storyBoard.instantiateViewController(withIdentifier: "chatVC") as! UINavigationController
// self.present(chatViewController, animated: true, completion: nil)
}
else {
DispatchQueue.main.async{
//Display Alert Message if login failed
let alertController = UIAlertController(title: "Error", message: error?.localizedDescription, preferredStyle: .alert)
let defaultAction = UIAlertAction(title: "OK", style: .cancel, handler: nil)
alertController.addAction(defaultAction)
self.present(alertController, animated: true, completion: nil)
}
}
}
}
For the first function, I get a position value, as stated in the print statement.
For the second function, my variable, "loggedOnUser" is empty.
You need a completion as loadUser is asynchronous
func loadUser(userid: String,completion:#escaping(User?) ->()) {
//print(userid)
let userid = "56ldZFJiv0dpfaABzo78"
var user = User()
let docRef = db.collection("users").document(userid)
docRef.getDocument { (document, error) in
if let document = document {
let first = document.data()!["first"] as! String
let last = document.data()!["last"] as! String
let position = document.data()!["position"] as! String
let company = document.data()!["company"] as! String
let email = document.data()!["email"] as! String
let address = document.data()!["address"] as! String
let userID = document.data()!["userID"] as! String
//Initalize user
user = User(userID: userID,
firstName: first,
lastName: last,
company: company,
address: address,
position: position,
email: email)
print(user.position)
completion(user)
} else {
print("Document does not exist")
completion(nil)
}
}
}
Call
self.loadUser(userid: Auth.auth().currentUser!.uid) { res in
if let user = res {
print(user)
}
}
Related
Everything was working fine, then I deleted some old messages and conversations from My Firebase Database. Now every time I send a message I get a crash. I deleted all old users and created new users and tried to send messages and I still keep getting a crash. I am not sure what can be causing this. Any suggestions will be helpful. It first happened after I tested out this function to delete the table cell...
func deleteConversation(_ conversation:Conversation) {
guard let user = Auth.auth().currentUser else { return }
let ref = Database.database().reference()
let obj = [
"conversations/users/\(user.uid)/\(conversation.partner_uid)/muted": true
] as [String:Any]
print("OBBJ: \(obj)")
ref.updateChildValues(obj, withCompletionBlock: { error, ref in
if error != nil {
let alert = UIAlertController(title: "Error deleting conversation!", message: nil, preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "Okay", style: .default, handler: nil))
} else {
let alert = UIAlertController(title: "Conversation deleted!", message: nil, preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "Okay", style: .default, handler: nil))
}
})
}
func downloadMessages() {
self.messages = []
downloadRef?.observe(.childAdded, with: { snapshot in
let dict = snapshot.value as! [String:AnyObject]
if let sender = dict["sender"] as! String!, let recipient = dict["recipient"] as! String!, let text = dict["text"] as! String!, text.characters.count > 0 {
let timestamp = dict["timestamp"] as! Double
let date = NSDate(timeIntervalSince1970: timestamp/1000)
let message = JSQMessage(senderId: sender, senderDisplayName: "", date: date as Date!, text: text)
self.messages.append(message!)
self.reloadMessagesView()
self.finishReceivingMessage(animated: true)
}
else if let id = dict["sender"] as! String!,
let photoURL = dict["imageUrl"] as! String!, photoURL.characters.count > 0 { // 1
// 2
if let mediaItem = JSQPhotoMediaItem(maskAsOutgoing: id == self.senderId) {
// 3
let timestamp = dict["timestamp"] as! Double
let date = NSDate(timeIntervalSince1970: timestamp/1000)
if let message = JSQMessage(senderId: id, senderDisplayName: "", date: date as Date!, media: mediaItem) {
self.messages.append(message)
if (mediaItem.image == nil) {
self.photoMessageMap[snapshot.key] = mediaItem
}
self.collectionView.reloadData()
}
if photoURL.hasPrefix("gs://") {
self.fetchImageDataAtURL(photoURL, forMediaItem: mediaItem, clearsPhotoMessageMapOnSuccessForKey: nil)
}
}
}
else {
print("Error! Could not decode message data")
}
})
// We can also use the observer method to listen for
// changes to existing messages.
// We use this to be notified when a photo has been stored
// to the Firebase Storage, so we can update the message data
updatedMessageRefHandle = downloadRef?.observe(.childChanged, with: { (snapshot) in
let key = snapshot.key
let messageData = snapshot.value as! Dictionary<String, String> // 1
if let photoURL = messageData["imageUrl"] as String! { // 2
// The photo has been updated.
if let mediaItem = self.photoMessageMap[key] { // 3
self.fetchImageDataAtURL(photoURL, forMediaItem: mediaItem, clearsPhotoMessageMapOnSuccessForKey: key) // 4
}
}
})
}
It's very likely the error is a result of force casting - as!
Instead of
let messageData = snapshot.value as! Dictionary<String, String>
do
guard let messageData = snapshot.value as? Dictionary<String, String> else { return }
Your snapshot.value is either nil, or is not an instance of Dictionary<String, String>, and force casting it to such will result in crash.
You should also read more about optionals and type casting in Swift, because you use ! a lot, and not once in your program is it used correctly.
I am taking the zip code entered by my user and converting it into a City name. After it is converted to the City name I will save the information into my Firebase Database. I am getting an error "Cannot convert value of type '()' to expected argument type 'String'" when I try to do this. I am getting the zip code from a text field and passing it from the previous ViewController.
error
//first ViewController
override func prepare(for segue: UIStoryboardSegue, sender: Any?)
{
if let destination = segue.destination as? SignUpSecondViewController{
destination.zipCode = zipCodeInput.text!
destination.name = nameText.text!
destination.email = emailText.text!
destination.password = passwordText.text!
destination.pictureData = userImageView.image!
}}
}
//second ViewController
var zipCode = String()
func getLocationFromPostalCode(postalCode : String){
let geocoder = CLGeocoder()
geocoder.geocodeAddressString(postalCode) {
(placemarks, error) -> Void in
// Placemarks is an optional array of type CLPlacemarks, first item in array is best guess of Address
if let placemark = placemarks?[0] {
if placemark.postalCode == postalCode{
// you can get all the details of place here
print("\(placemark.locality)")
print("\(placemark.country)")
}
else{
print("Please enter valid zipcode")
}
}
}
}
#IBAction func completeButtonAction(_ sender: Any) {
let nameText = name
let emailField = email.lowercased()
let finalEmail = emailField.trimmingCharacters(in: .whitespacesAndNewlines)
let location = getLocationFromPostalCode(postalCode: zipCode)
let biography = bioTextView.text!
let passwordText = password
let interests = options.joined(separator: " , ")
var pictureD: NSData?
if let imageView = self.sentPic.image {
pictureD = UIImageJPEGRepresentation(self.sentPic.image!, 0.70) as! NSData
}
if finalEmail.isEmpty || biography.isEmpty || password.isEmpty || pictureD == nil {
self.view.endEditing(true)
let alertController = UIAlertController(title: "OOPS", message: " You must fill all the fields", preferredStyle: .alert)
alertController.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: nil))
present(alertController, animated: true, completion: nil)
}else {
SVProgressHUD.show()
self.view.endEditing(true)
authService.signUP(firstLastName: nameText, email: finalEmail, location: location, biography: biography, password: password, interests: interests, pictureData: pictureD as NSData!)
}
SVProgressHUD.dismiss()
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let vc = storyboard.instantiateViewController(withIdentifier: "NewTabBarViewController") as! UIViewController
// Alternative way to present the new view controller
self.navigationController?.present(vc, animated: true, completion: nil)
}
Your problem begins with this line:
let location = getLocationFromPostalCode(postalCode: zipCode)
The problem is that your getLocationFromPostalCode has no return value so the compiler thinks that the implicit type of location is () which means a function with no return (void) type.
So, in theory, you would want to change:
func getLocationFromPostalCode(postalCode : String) {
to:
func getLocationFromPostalCode(postalCode : String) -> String {
and have the function return a String value.
But, you can't do that either since the implementation of your getLocationFromPostalCode consists of getting the location from an asynchronous network call.
The proper solution is to rewrite that function to take a completion handler that returns the obtained location.
func getLocationFromPostalCode(postalCode: String, completion: (String?) -> Void) {
let geocoder = CLGeocoder()
geocoder.geocodeAddressString(postalCode) { (placemarks, error) -> Void in
// Placemarks is an optional array of type CLPlacemarks, first item in array is best guess of Address
if let placemark = placemarks?.first {
if placemark.postalCode == postalCode {
// you can get all the details of place here
print("\(placemark.locality)")
print("\(placemark.country)")
completion(placemark.locality) // or whatever value you want
return
}
else{
print("Please enter valid zipcode")
}
}
completion(nil) // no location found
}
}
Now, with that all fixed up, you need to redo how you get the location.
#IBAction func completeButtonAction(_ sender: Any) {
var pictureD: Data? = nil
if let imageView = self.sentPic.image {
pictureD = UIImageJPEGRepresentation(imageView, 0.70)
}
let emailField = email.lowercased()
let finalEmail = emailField.trimmingCharacters(in: .whitespacesAndNewlines)
let biography = bioTextView.text!
let passwordText = password
if finalEmail.isEmpty || biography.isEmpty || password.isEmpty || pictureD == nil {
self.view.endEditing(true)
let alertController = UIAlertController(title: "OOPS", message: " You must fill all the fields", preferredStyle: .alert)
alertController.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: nil))
present(alertController, animated: true, completion: nil)
}else {
getLocationFromPostalCode(postalCode: zipCode) { (location) in
guard let location = location else {
print("no location")
return
}
let nameText = name
let interests = options.joined(separator: " , ")
SVProgressHUD.show()
self.view.endEditing(true)
authService.signUP(firstLastName: nameText, email: finalEmail, location: location, biography: biography, password: password, interests: interests, pictureData: pictureD!)
SVProgressHUD.dismiss()
}
}
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let vc = storyboard.instantiateViewController(withIdentifier: "NewTabBarViewController") as! UIViewController
// Alternative way to present the new view controller
self.navigationController?.present(vc, animated: true, completion: nil)
}
So I am having an issue with my code. My signup page grabs the user data. It gets the username, location, and profile pic. Everything works right it seems everything is being saved to firebase. However when the account is created and I go to the user profile everything seems to be nil.
This is my function that handles the sign up.
#objc func handleSignUp(){
// first we cant to take sure that all of the fields are filled
let bio: String = ""
var profilePic: String = ""
// will take the user selected image and load it to firebase
let imageName = NSUUID().uuidString
let storageRef = Storage.storage().reference().child("profile_images").child("\(imageName).PNG")
if let userImage = selectedImageFromPicker,let uploadData = UIImageJPEGRepresentation(userImage, 0.1){
storageRef.putData(uploadData, metadata: nil, completion: { (metadata, error) in
if error != nil{
print(error ?? "")
return
}
profilePic = (metadata?.downloadURL()!.absoluteString)!
guard let username = self.nameTextField.text,
let confirmPassword = self.confirmPasswordTextField.text,
let email = self.emailTextField.text,
let password = self.passwordTextField.text,
!username.isEmpty,
!email.isEmpty,
!password.isEmpty,
!confirmPassword.isEmpty
else {
print("Required fields are not all filled!")
return
}
if self.validateEmail(enteredEmail:email) != true{
let alertController = UIAlertController(title: "Error", message: "Please Enter A Valid Email", preferredStyle: .alert)
let defaultAction = UIAlertAction(title: "Ok", style: .cancel, handler: nil)
alertController.addAction(defaultAction)
self.present(alertController, animated: true, completion: nil)
}
// will make sure user is validated before it even tries to create user
// will make sure the password and confirm password textfields have the same value if so it will print an error
if self.passwordTextField.text != self.confirmPasswordTextField.text {
let alertController = UIAlertController(title: "Error", message: "Passwords Don't Match", preferredStyle: .alert)
let defaultAction = UIAlertAction(title: "Ok", style: .cancel, handler: nil)
alertController.addAction(defaultAction)
self.present(alertController, animated: true, completion: nil)
}
// will authenticate a user into the authentication services with an email and passowrd
AuthService.createUser(controller: self, email: email, password: password) { (authUser) in
guard let firUser = authUser else {
return
}
//will add user to the database
print(profilePic)
print(username)
UserService.create(firUser, username: username , profilePic: profilePic , bio: bio, location: self.userLocation!) { (user) in
guard let user = user else {
print("User successfully loaded into firebase db")
return
}
// will set the current user for userdefaults to work
print(user.profilePic)
print(user.username)
User.setCurrent(user, writeToUserDefaults: true)
// self.delegate?.finishSigningUp()
self.finishSigningUp()
}
}
})
}
}
This is my viewdidload for the profile controller. When I print out the user here everything is nil.
override func viewDidLoad() {
super.viewDidLoad()
collectionView?.backgroundColor = UIColor.white
let user = self.user ?? User.current
profileHandle = UserService.observeProfile(for: user) { [unowned self](ref, user, events) in
self.profileRef = ref
self.user = user
self.userEvents = events
// self.jobs = allJobs
// self.reciepts = allReciepts
// print(self.userEvents)
// print(self.reciepts)
DispatchQueue.main.async {
self.collectionView?.reloadData()
}
}
This handles the transition to the homepage.
func finishSigningUp() {
print("Finish signing up from signup view controller")
print("Attempting to return to root view controller")
let homeController = HomeViewController()
//should change the root view controller to the homecontroller when done signing up
self.view.window?.rootViewController = homeController
self.view.window?.makeKeyAndVisible()
}
My home view controller controls the navigation of these throguh a snapcaht style swiping which is controlled using an array of view controllers. Like so
lazy var viewControllerList: [UIViewController] = {
let homeFeedController = HomeFeedController()
let navController = UINavigationController(rootViewController: homeFeedController)
// let navController = ScrollingNavigationController(rootViewController: homeFeedController)
let profileView = ProfileeViewController(collectionViewLayout: UICollectionViewFlowLayout())
let profileViewNavController = UINavigationController(rootViewController: profileView)
let searchController = EventSearchController(collectionViewLayout: UICollectionViewFlowLayout())
let searchNavController = UINavigationController(rootViewController: searchController)
return [searchNavController,navController,profileViewNavController]
}()
Obseverprofile function
// will observe the user object in the database for any changes and make sure that they are updated
static func observeProfile(for user: User, completion: #escaping (DatabaseReference, User?, [Event]) -> Void) -> DatabaseHandle {
// 1
let userRef = Database.database().reference().child("users").child(user.uid)
// 2
return userRef.observe(.value, with: { snapshot in
// 3
guard let user = User(snapshot: snapshot) else {
return completion(userRef, nil, [])
}
// print(user)
// 4
Events(for: user, completion: { events in
// 5
completion(userRef, user, events)
})
})
}
User Model
import Foundation
import FirebaseDatabase.FIRDataSnapshot
class User : NSObject {
//User variables
let uid : String
let username : String?
let profilePic: String?
var location: String?
var isFollowed = false
let bio: String?
var dictValue: [String : Any] {
return ["username" : username as Any,
"profilePic" : profilePic as Any,
"Bio" : bio as Any, "location": location as Any]
}
//Standard User init()
init(uid: String, username: String, profilePic: String, bio: String, location: String = "") {
self.uid = uid
self.username = username
self.profilePic = profilePic
self.bio = bio
self.location = location
super.init()
}
//User init using Firebase snapshots
init?(snapshot: DataSnapshot) {
guard let dict = snapshot.value as? [String : Any],
let username = dict["username"] as? String,
let profilePic = dict["profilePic"] as? String,
let bio = dict["bio"] as? String,
let location = dict["location"] as? String
else { return nil }
self.uid = snapshot.key
self.location = location
self.username = username
self.profilePic = profilePic
self.bio = bio
}
//UserDefaults
required init?(coder aDecoder: NSCoder) {
guard let uid = aDecoder.decodeObject(forKey: "uid") as? String,
let username = aDecoder.decodeObject(forKey: "username") as? String,
let profilePic = aDecoder.decodeObject(forKey: "profilePic") as? String,
let bio = aDecoder.decodeObject(forKey: "bio") as? String,
let location = aDecoder.decodeObject(forKey: "location") as? String
else { return nil }
self.uid = uid
self.username = username
self.profilePic = profilePic
self.bio = bio
self.location = location
super.init()
}
init?(key: String, postDictionary: [String : Any]) {
//var dict : [String : Any]
//print(postDictionary as? [String:])
let dict = postDictionary
print(dict)
let profilePic = dict["profilePic"] as? String ?? ""
let bio = dict["bio"] as? String ?? ""
let username = dict["username"] as? String ?? ""
let location = dict["location"] as? String ?? ""
self.uid = key
self.location = location
self.profilePic = profilePic
self.username = username
self.bio = bio
}
//User singleton for currently logged user
private static var _current: User?
static var current: User {
guard let currentUser = _current else {
fatalError("Error: current user doesn't exist")
}
return currentUser
}
class func setCurrent(_ user: User, writeToUserDefaults: Bool = true) {
print(user)
print("")
if writeToUserDefaults {
let data = NSKeyedArchiver.archivedData(withRootObject: user)
UserDefaults.standard.set(data, forKey: "currentUser")
UserDefaults.standard.synchronize()
}
_current = user
print(_current)
}
}
extension User: NSCoding {
func encode(with aCoder: NSCoder) {
aCoder.encode(uid, forKey: "uid")
aCoder.encode(username, forKey: "username")
aCoder.encode(profilePic, forKey: "profilePic")
aCoder.encode(bio, forKey: "bio")
aCoder.encode(location, forKey: "location")
}
}
This code keeps overwriting the database after a new user is created. This is the code that I have put in:
func handleRegister() {
guard let email = emailTextField.text, let password = passwordTextField.text, let name = nameTextField.text
else {
print("Form is not Valid")
return
}
Auth.auth().createUser(withEmail: email, password: password, completion: {(user: User?, error) in
if error != nil {
print(Error.self)
return
}
guard (user?.uid) != nil else { return }
})
let ref = Database.database().reference(fromURL: "//Firebase link")
let usersReference = ref.child("Users").child("uid")
let values = ["name": name, "email": email]
usersReference.updateChildValues(values, withCompletionBlock: { (err, ref) in
if err != nil {
print(err.self)
return
}
print("Successfully saved user in Firebase DB")
})
}
I feel like I'm missing something really simple. Any help would be appreciated.
EDIT:
after your
guard (user?.uid) != nil else {
return
}
put your remaining code below it:
let ref = Database.database()... //your code
//put inside the completion block of create user
//the rest of your code up to the updateChildValues
and use this uid as the parameter for your child in users
so it would become:
let usersReference = ref.child("Users").child(uid)
note that the uid is not enclosed with double quotes
you have to put it inside the createUser completion block because the scope of your user?.uid is only up to that block.
use below code as in your code everytime you run handler data is replaced as you are providing static "uid" use below code to add a node with current user uid which is assigned to user at time of account creation in firebase DB
//before viewDidLoad declare a global databaseRef as
let databaseRef = Database.Database().reference //this will be used as base reference In all handlers
var name : String = ""
var Uid : String = ""
var email : String = ""
var nameString : String = ""
func createUser(){
Auth.auth().createUser(withEmail: self.EmailTextField.text!, password: self.PasswordTextField.text!) { (user, error) in
if error == nil {
print("You have successfully signed up")
//Goes to the Setup page which lets the user take a photo for their profile picture and also chose a username
self.nameString = self.nameTextField.text!
self.AddUserDetails()
DispatchQueue.main.async(execute: {
let vc = self.storyboard?.instantiateViewController(withIdentifier: "Main")
self.present(vc!, animated: true, completion: nil)
})
} else {
//this block shows error if exist
let alertController = UIAlertController(title: "Error", message: error?.localizedDescription, preferredStyle: .alert)
let defaultAction = UIAlertAction(title: "OK", style: .cancel, handler: nil)
alertController.addAction(defaultAction)
self.present(alertController, animated: true, completion: nil)
//this is my activity indicator
self.spinnerView.isHidden = true
self.spinner.isHidden = true
self.spinner.stopAnimating()
}
}
}
func AddUserDetails(){
//I make use of user nsobject class to get all details
//you can also make use of some global strings
self.name = self.nameString //name string store current display name
//name string contains name which I am taking as input when a user want to sign up as a textField text
self.email = (Auth.auth().currentUser?.email)! //current email
self.Uid = (Auth.auth().currentUser?.uid)! //current uid
let user:[String : AnyObject] = ["email": self.email as AnyObject,"name":self.name as AnyObject,"uID":self.Uid as AnyObject]
databaseRef.child("users").child(self.Uid).setValue(user)
}
you are not calling your code to write in database inside the callback of user creation. So its creating user reference with old uid and hence overwrite the values.
Auth.auth().createUser(withEmail: email, password: password, completion: {(user: User?, error) in
if error != nil {
print(Error.self)
return
}
// after this you are sure user created and now move your calls here
//to write in firebase database.
guard (user?.uid) != nil else {
return
}
})
How can i upload a row in Parse.com?
This is my query code:
func queryFromParse(){
self.arrayOfDetails.removeAll()
let query = PFQuery(className: "currentUploads")
query.orderByDescending("createdAt")
query.findObjectsInBackgroundWithBlock { (objects:[AnyObject]?, error:NSError?) -> Void in
if error == nil
{
if let newObjects = objects as? [PFObject] {
for oneobject in newObjects {
let text = oneobject["imageText"] as! String
let username = oneobject["username"] as! String
let deviceID = oneobject["identifierForVendor"] as! String
let reportedCount = oneobject["reportedCount"] as! String
let time = oneobject.createdAt!
if let userImage = oneobject["imageFile"] as? PFFile {
let userImage = oneobject["imageFile"] as! PFFile
let imageURL = userImage.url // <- Bruker nĂ¥ userImage.URL, henter ikke bildefilen med en gang
let OneBigObject = Details(username: username, text: text, CreatedAt: time, image: imageURL!, deviceID: deviceID, reportedCount: reportedCount)
//let OneBigObject = Details(username: username, text: text, CreatedAt: time, image: imageURL!)
self.arrayOfDetails.append(OneBigObject)
dispatch_async(dispatch_get_main_queue()) { self.collectionView.reloadData() }
}
}
}
}
}
}
Image here
I want to update the "reportedCount" when the image is reported. I have a code that i have been using, but that created new rows in another class for each report, and I want only to update the "reportedCount":
#IBAction func reportContentAction(sender: AnyObject) {
let buttonPosition = sender.convertPoint(CGPointZero, toView: self.collectionView)
let indexPath = self.collectionView.indexPathForItemAtPoint(buttonPosition)
////
println(indexPath?.item)
////
let post = self.arrayOfDetails[indexPath!.item]
var alertMessage = NSString(format:"*User: %#\r *Text: %#\r *Created at %#", post.username, post.text, post.CreatedAt)
var reportAlert = UIAlertController(title: "Report Content", message:alertMessage as String, preferredStyle: UIAlertControllerStyle.Alert)
reportAlert.addAction(UIAlertAction(title: "Yes", style: .Default, handler: { (action: UIAlertAction!) in
println("Handle Report Logic here")
var currentUploads = PFObject(className: "banned")
currentUploads["username"] = post.username
currentUploads["imageText"] = post.text
currentUploads["imageFile"] = post.image
currentUploads["identifierForVendor"] = post.deviceID
currentUploads["flaggedBy"] = PFUser.currentUser()?.username
currentUploads["flaggedByUUID"] = UIDevice.currentDevice().identifierForVendor.UUIDString
currentUploads.saveInBackgroundWithBlock({ (success: Bool, error: NSError?) -> Void in
if error == nil{
//**Success saving, now save image.**//
currentUploads.saveInBackgroundWithBlock({ (success: Bool, error: NSError?) -> Void in
if error == nil{
// Take user home
print("Data uploaded")
// Show UIAlertView
let alert = UIAlertView()
alert.title = "Message"
alert.message = "You report has been sent. Thank you for your support."
alert.addButtonWithTitle("Close")
alert.show()
}
else{
print(error)
}
})
}
else{
print(error)
}
})
}))
reportAlert.addAction(UIAlertAction(title: "Cancel", style: .Default, handler: { (action: UIAlertAction!) in
println("Handle Cancel Logic here")
}))
presentViewController(reportAlert, animated: true, completion: nil)
}
You should be keeping a reference to oneobject, or more broadly, all of the objects returned from the query. Now when something changes you can get the appropriate instance from the objects array and then update and save it to modify the existing 'row'.