PFObject does not reflect "successfully" saved changes in the Parse Data Browser - ios

I am trying to update a PFObject called message. This PFObject has already been retrieved from the Parse Database and passed over from another view controller. I know that the PFObject is passed over correctly because I can NSLog it's value and it is correct.
With the following code, I add an object to one of the PFObject's keys:
[self.message addObject:#"blah" forKey:#"didRespond"];
I then try saving the updated PFObject to the Parse Database:
[self.message saveInBackgroundWithBlock:^(BOOL succeeded, NSError *error) {
if (error) {
NSLog(#"An error has occurred.");
}
}];
The above method always calls back with a succeeded value of 1, and there are never any errors. However, when I go and look at the PFObject in the Parse Data Browser, it's key does not contain the newly added object. It is still completely empty.
They key is an array, so I know I should be using addObject: and not setObject:
I have several other Parse saves happening in this same view controller, and throughout my app, and they all work perfectly fine, but for some reason this one will not. I have tried every type of save method Parse offers, including the synchronous save method, but nothing works.
What is even more strange, is this is a new version of my app and I am refactoring the code. My old version contains a giant mess of code, but what's amazing is the same PFObject is successfully updated in this old code! I even tried copying and pasting this code to my new version and it will not work, even though it will in the old version.
Here is the giant mess of code from my old version. If you search for the following code statement you will be able to locate it quickly:
[self.message addObject:currentUsersObjectId forKey:#"didRespond"];
Here is the full chunk of code, where the save is working and being reflected in the Data Browser. It consists of several nested asynchronous Parse saves:
-(void)uploadPhoto {
NSLog(#"self.image.size right before upload: %#", NSStringFromCGSize(self.image.size));
NSString *fileType;
NSString *halfOrFull;
if(self.image != nil) {
fileType = #"image";
halfOrFull = #"full";
NSData *imageData = UIImageJPEGRepresentation(self.image, 0.7);
PFFile *imageFile = [PFFile fileWithName:#"Image.jpg" data:imageData];
NSString *originalSender = [[NSString alloc]init];
originalSender = [self.message objectForKey:#"senderId"];
NSLog(#"PFFile has been created: %#", imageFile);
[imageFile saveInBackgroundWithBlock:^(BOOL succeeded, NSError *error) {
if(error) {
NSLog(#"There has been an error: %# %#", error, [error userInfo]);
UIAlertView *alertView = [[UIAlertView alloc]initWithTitle:#"An error occurred!" message:#"Please try sending your message again." delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alertView show];
} else {
[self.afterPhotoView setHidden:YES];
PFObject *returnMessage = [PFObject objectWithClassName:#"Messages"];
[returnMessage setObject:imageFile forKey:#"file"];
[returnMessage setObject:fileType forKey:#"fileType"];
[returnMessage addObject:originalSender forKey:#"recipientIds"];
[returnMessage setObject:[[PFUser currentUser]objectId] forKey:#"senderId"];
[returnMessage setObject:[[PFUser currentUser]username]forKey:#"senderName"];
[returnMessage setObject:halfOrFull forKey:#"halfOrFull"];
NSString *originalSender = [[NSString alloc]init];
originalSender = [self.message objectForKey:#"senderName"];
[returnMessage setObject:originalSender forKey:#"originalSender"];
[returnMessage saveInBackgroundWithBlock:^(BOOL succeeded, NSError *error) {
if(error) {
NSLog(#"There was an error: %# %#", error, [error userInfo]);
UIAlertView *alertView = [[UIAlertView alloc]initWithTitle:#"An error occurred!" message:#"Please try sending your message again." delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alertView show];
} else {
//Everything was successful.
NSLog(#"Everything was successful.");
if(succeeded == 1) {
NSLog(#"Succeeded value right before 2nd save: %d", succeeded);
NSString *currentUsersObjectId = [[NSString alloc]init];
PFUser *user = [PFUser currentUser];
currentUsersObjectId = user.objectId;
[self.message addObject:currentUsersObjectId forKey:#"didRespond"];
[self.message saveInBackgroundWithBlock:^(BOOL succeeded, NSError *error) {
if(error) {
NSLog(#"There was an error: %# %#", error, [error userInfo]);
self.uploadPhotoAlertView = [[UIAlertView alloc]initWithTitle:#"An error occurred!" message:#"Please try sending your message again." delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil];
[self.uploadPhotoAlertView show];
} else {
//Everything was successful.
NSLog(#"Everything was successful.");
if(succeeded == 1) {
//[self performSegueWithIdentifier:#"segueToInbox" sender:self];
NSString *originalSender2 = [[NSString alloc]init];
originalSender2 = [self.message objectForKey:#"senderName"];
self.photoUploadAlertViewMessage = [[NSString alloc]initWithFormat:#"You just finished going halfsies with %#!", originalSender2];
//PFFile *imageFile = [self.message objectForKey:#"file"];
self.finishedImageFile = imageFile;
self.finishedImageFileURL = [[NSURL alloc]initWithString:self.finishedImageFile.url];
self.uploadPhotoAlertView = [[UIAlertView alloc]initWithTitle:nil message:self.photoUploadAlertViewMessage delegate:self cancelButtonTitle:#"Sweet!" otherButtonTitles:nil];
[self.uploadPhotoAlertView show];
//[self.sharePhotoView setHidden:NO];
}
//[self performSegueWithIdentifier:#"segueToInbox" sender:self];
}
}];
}
}
}];
}
}];
}
}

Related

I'm working on an app like instagram

I need help posting a picture onto a tableview after i posted to parse. I am using parse and objective-c. I got to where you can post a picture and I can see it on parse, but how can I see the picture on like a timeline in my app or a table view?
Here is my code for posting to parse,
- (IBAction)uploadButton:(id)sender{
NSData* data = UIImageJPEGRepresentation(_imageView.image, 100);
PFFile *imageFile = [PFFile fileWithName:#"Image.jpg" data:data];
// Save the image to Parse
[imageFile saveInBackgroundWithBlock:^(BOOL succeeded, NSError *error) {
if (!error) {
// The image has now been uploaded to Parse. Associate it with a new object
PFObject* newPhotoObject = [PFObject objectWithClassName:#"PhotoObject"];
[newPhotoObject setObject:imageFile forKey:#"image"];
[newPhotoObject saveInBackgroundWithBlock:^(BOOL succeeded, NSError *error) {
if (!error) {
NSLog(#"Saved");
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Success" message:#"Your picture has been successfully uploaded." delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alert show];
}
else{
// Error
NSLog(#"Error: %# %#", error, [error userInfo]);
}
}];
}
}];
}
What else do I need to put in order to see what I posted on my main tableview page?
I labeled the view controllers "posting page" and the "main page". The "main page" is where I want all the pictures I post to parse to end up, with a comment section for the picture.
i have done like this , may be useful to you. take a look
-(IBAction)btnUpDateImageClicked:(id)sender
{
if (UserSelectedImage)
{
HUDSHOWWITHTEXT(#"Updating profile");
PFQuery *query = [PFQuery queryWithClassName:User_Info];
NSLog(#"->%#",[PFUser currentUser].username);
[query whereKey:UserName equalTo:[PFUser currentUser].username];
[query getFirstObjectInBackgroundWithBlock:^(PFObject * user , NSError *error) {
if (!error) {
// Found User and modify it
PFFile *imageFile1,*imageFilePlaceHolder;
NSData *imageData1,*imageDataPlaceHolder;
// PFFile *fileDeleted = [[PFFile alloc] init];
if (UserSelectedImage) {
//User image
imageData1 = UIImageJPEGRepresentation(UserSelectedImage, 1.0);
imageFile1 = [PFFile fileWithName:#"img.png" data:imageData1];
[user setObject:imageFile1 forKey:#"user_image"];
//PlaceHolder
UIImage *imagPlaceholder = UserSelectedImage;
imagPlaceholder = [APP_DELEGATE SyncPlaceHolderImage:imagPlaceholder];
imageDataPlaceHolder = UIImageJPEGRepresentation(imagPlaceholder, 1.0);
imageFilePlaceHolder = [PFFile fileWithName:#"img.png" data:imageDataPlaceHolder];
[user setObject:imageFilePlaceHolder forKey:#"placeholder_image"];
}
else {
user[#"user_image1"] = [NSNull null];
user[#"placeholder_image"] = [NSNull null];
}
// Save
[user saveInBackgroundWithBlock:^(BOOL succeeded, NSError *error) {
if (succeeded) {
HUDHIDE;
if (UserSelectedImage) {
APP_DELEGATE.user.pfImageOne = imageFile1;
APP_DELEGATE.user.pfImagePlaceHolder= imageFilePlaceHolder;
}
else {
APP_DELEGATE.user.pfImageOne = nil;
APP_DELEGATE.user.pfImagePlaceHolder=nil;
}
ShowAlert(#"Saved SUccesfully");
}
else
{
HUDHIDE;
ShowAlert(#"Problem updating profile-%#");
}
}];
} else {
// Did not find any UserStats for the current user
NSLog(#"Error: %#", error);
HUDHIDE;
ShowAlert(#"Problem updating profile")
}
}];
}
else
{
ShowAlert(#"please select Image");
}
}

How to pause a main thread until a block is finished Objective-C

I have a problem.
-(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info{
UIImage* image = [info objectForKey:UIImagePickerControllerOriginalImage];
UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil);
[self dismissViewControllerAnimated:YES completion:^{
if (image == nil){
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Try again !" message:#"Please try again." delegate:self cancelButtonTitle:#"OK" otherButtonTitles: nil];
[alert show];
[self presentViewController:self.imagePicker animated:NO completion:nil];
}else{
NSData *fileData;
NSString *fileName;
NSString *fileType;
fileData = UIImagePNGRepresentation(image);
fileName = #"profilePic.png";
fileType = #"Image";
PFFile *file = [PFFile fileWithName:fileName data:fileData];
[file saveInBackgroundWithBlock:^(BOOL succeeded, NSError *error) {
if (error) {
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:#"An error occurred!"
message:[NSString stringWithFormat:#"Please try sending your message again. %#",error.userInfo]
delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alertView show];
}else{
[[PFUser currentUser]setObject:file forKey:#"profilePic"];
[[PFUser currentUser] saveInBackgroundWithBlock:^(BOOL succeed, NSError* error){
if (!error) {
NSLog(#"New profile pic loaded.");
[self.activity stopAnimating];
[self.reloadPicBtn setHidden:NO];
}else{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Try again !" message:#"Please try again. Failed to load your new profile pic :(" delegate:self cancelButtonTitle:#"OK" otherButtonTitles: nil];
[alert show];
}
}];
}
}];
}
}];
}
Well, reloadPicBtn is shown, but if I call a function which reloads a picture, It fails. And when I try to understand WTF is going on using NSLog it logs out a string. So code has been executed. But there is no result on screen. The function is the same which is called in viewDidLoad. But it works when it is called from viewDidLoad. And when it is called again there is no result.
That reload function:
- (void) loadProfilePic{
PFQuery* query = [PFUser query];
[query getObjectInBackgroundWithId:[PFUser currentUser].objectId block:^(PFObject* object, NSError* error){
if(!error){
PFFile* imageFile = object[#"profilePic"];
[imageFile getDataInBackgroundWithBlock:^(NSData* data, NSError* error){
if (!error) {
self.activity.hidden = NO;
[self.activity startAnimating];
self.profilePic.image = [UIImage imageWithData:data];
NSLog(#"Profile pic shown");
}
else{
NSLog(#"Error 2: %#",error);
}
}];
}else{
self.profilePic.image = [UIImage imageNamed:#"profile#2.png"];
NSLog(#"Fail 1 : %#",error);
}
}];
}
Please help me.
It prints out profile pic shown. But it doesn't even use network to download an image.

Missing user password in Parse log in

Below is my code for phone number verification. First we query to check if user already exists; if so, I want to log in with that user. If not, I create a new PFUser.
- (IBAction)confirmButtonTapped:(id)sender
{
// Check to see if a valid phone number is entered
if ([self.phoneNumberTextField.text hasPrefix:#"+56"] && self.phoneNumberTextField.text.length == 12){
self.phoneNumber = [self phoneNumberWithoutSpaces:self.phoneNumberTextField.text];
// Check if phone number is already assigned to a Parse user
PFQuery *phoneNumberQuery = [PFUser query];
[phoneNumberQuery whereKey:#"phoneNumber" equalTo:self.phoneNumber];
[phoneNumberQuery findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error){
if (!error){
if (objects.count > 0){
// Move on to main tab bar and log in with user found
PFUser *user = [objects objectAtIndex:0];
[PFUser logInWithUsernameInBackground:user.username password:user.password block:^(PFUser *user, NSError *error){
if (!error){
[[NSUserDefaults standardUserDefaults] setValue:[NSNumber numberWithBool:YES] forKey:#"recoverUser"];
[[NSUserDefaults standardUserDefaults] synchronize];
NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:self.phoneNumber, #"phoneNumber", nil];
[PFCloud callFunctionInBackground:#"sendVerificationCode" withParameters:dict block:^(id object, NSError *error){
if (error){
NSLog(#"Error calling cloud function: %#", error.localizedDescription);
}
}];
[self performSegueWithIdentifier:#"confirmNumberSegue" sender:self];
} else {
NSLog(#"Error logging in: %#", error.localizedDescription);
[[[UIAlertView alloc] initWithTitle:#"Connection Failed" message:#"Please try again." delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil] show];
}
}];
} else {
[[NSUserDefaults standardUserDefaults] setValue:[NSNumber numberWithBool:NO] forKey:#"recoverUser"];
[[NSUserDefaults standardUserDefaults] synchronize];
//Create new Parse user
[self createNewUser];
}
} else {
NSLog(#"Error fetching user object: %#", error.localizedDescription);
[[[UIAlertView alloc] initWithTitle:#"Connection Failed" message:#"Please try again." delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil] show];
}
}];
} else {
[[[UIAlertView alloc] initWithTitle:#"Invalid Phone Number" message:#"Please enter a valid phone number." delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil] show];
}
}
I am getting a Parse error when trying to log in (Code: 201) Missing user password.

Parse 122 error upload

If I save text without having any text in the field I get this error message in Parse.com: Update Failure - The operation couldn't be completed(Parse error 122.) If I press OK and then try to dismiss the view with Cancel(a button item) the app crashes. I think a valid file name at Parse.com has to contain at least 1 character. Maybe I can do do something to stop the user from saving when not enter text? Any ideas?
This my code:
- (IBAction)save:(id)sender {
// Create PFObject with profile information
PFUser *profile = [PFUser currentUser];
[profile setObject:nameTextField.text forKey:#"name"];
[profile setObject:titleTextField.text forKey:#"title"];
[profile setObject:locationTextField.text forKey:#"location"];
// Profile image
NSData *imageData = UIImageJPEGRepresentation(profileImageView.image, 0.8);
NSString *filename = [NSString stringWithFormat:#"%#", nameTextField.text];
PFFile *imageFile = [PFFile fileWithName:filename data:imageData];
[profile setObject:imageFile forKey:#"profileimageFile"];
// Show progress
MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:self.view animated:YES];
hud.mode = MBProgressHUDModeIndeterminate;
hud.labelText = #"Updating";
[hud show:YES];
// Upload profile to Parse
if(nameTextField.text.length==0 && titleTextField.text.length==0 && locationTextField.text.length==0)
[hud hide:YES];
[profile saveInBackgroundWithBlock:^(BOOL succeeded, NSError *error) {
if (error) {
[[[UIAlertView alloc] initWithTitle:#"Profile Information" message:#"Fill in atleast one field" delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil]show];
[hud hide:YES];
}
else {
// Show success message
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"" message:#"Successfully updated profile" delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil, nil];
[alert show];
[hud hide:YES];
[self dismissViewControllerAnimated:YES completion:nil];
[self performSegueWithIdentifier:#"profile" sender:self];
}
}];
}
- (IBAction)Cancel:(id)sender {
[self dismissViewControllerAnimated:YES completion:nil];
[self performSegueWithIdentifier:#"profile" sender:self];
}
1
Test if your one letter theory is true. Change:
NSString *filename = [NSString stringWithFormat:#"%#", nameTextField.text];
To:
NSString *filename = [NSString stringWithFormat:#"file%#", nameTextField.text];
2
Or just avoid it if it's blank. So this:
NSString *filename = [NSString stringWithFormat:#"%#", nameTextField.text];
PFFile *imageFile = [PFFile fileWithName:filename data:imageData];
[profile setObject:imageFile forKey:#"profileimageFile"];
Becomes:
if (nameTextField.text) {
NSString *filename = [NSString stringWithFormat:#"%#", nameTextField.text];
PFFile *imageFile = [PFFile fileWithName:filename data:imageData];
[profile setObject:imageFile forKey:#"profileimageFile"];
}
3
Also, what is this:
if(nameTextField.text.length==0 && titleTextField.text.length==0 && locationTextField.text.length==0)
It's doesn't appear to be connected to anything?
4
You call this twice in quick succession, and then again right after the file saves. Is there something in the method that makes the repetitive calls necessary?
[hud hide:YES];
5
Your if statement doesn't appear to be connected to anything:
if(nameTextField.text.length==0 && titleTextField.text.length==0 && locationTextField.text.length==0)
I'm assuming you want:
if(nameTextField.text.length==0 && titleTextField.text.length==0 && locationTextField.text.length==0) {
[hud hide:YES];
[profile saveInBackgroundWithBlock:^(BOOL succeeded, NSError *error) {
if (error) {
[[[UIAlertView alloc] initWithTitle:#"Profile Information" message:#"Fill in atleast one field" delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil]show];
[hud hide:YES];
}
else {
// Show success message
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"" message:#"Successfully updated profile" delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil, nil];
[alert show];
[hud hide:YES];
[self dismissViewControllerAnimated:YES completion:nil];
[self performSegueWithIdentifier:#"profile" sender:self];
}
}];
}

Issue with User Photo (Profile Picture) with parse

I have some issues with user photos (profile pictures). For every time a single user update his profile picture, it also updates the rest of the users with the same image. How do I change it so it doesn't change everywhere? I am using parse.com
I'm using following codes.
Uploading the photo:
- (void)uploadProfilePhoto {
NSData *imageData;
NSString *imageName;
NSString *imageType;
//Shrink it
//Upload profile photo
(self.image != nil); {
UIImage *resizeImage = [self resizeImage:self.image toWidth:320.0f andHeight:320.0f];
imageData = UIImagePNGRepresentation(resizeImage);
imageName = #"profileimage.png";
imageType = #"image";
}
PFFile *image = [PFFile fileWithName:imageName data:imageData];
[image saveInBackgroundWithBlock:^(BOOL succeeded, NSError *error) {
if (error) {
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:#"Something went wrong!" message:#"Please try again." delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alertView show];
}
else {
PFObject *UserPhotos = [PFObject objectWithClassName:#"UserPhoto"];
[UserPhotos setObject:image forKey:#"image"];
[UserPhotos setObject:imageType forKey:#"imageType"];
[UserPhotos setObject:[PFUser currentUser] forKey:#"user"];
[UserPhotos setObject:[[PFUser currentUser] objectId] forKey:#"uploaderId"];
[UserPhotos setObject:[[PFUser currentUser] username] forKey:#"uploaderUsername"];
[UserPhotos saveInBackgroundWithBlock:^(BOOL succeeded, NSError *error) {
if (error) {
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:#"Something went wrong!" message:#"Please try uploading your photo again." delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alertView show];
}
else {
//Everything was successfull!
}
}];
}
}];
}
When I retrieve the photo:
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
PFQuery *query = [PFQuery queryWithClassName:#"UserPhoto"];
[query includeKey:#"user"];
[query orderByDescending:#"createdAt"];
[query getFirstObjectInBackgroundWithBlock:^(PFObject *object, NSError *error) {
if (!object) {
return NSLog(#"%#", error);
}
PFFile *imageFile = object[#"image"];
[imageFile getDataInBackgroundWithBlock:^(NSData *data, NSError *error) {
if (!data) {
return NSLog(#"%#", error);
}
// Do something with the image
self.profileImage.image = [UIImage imageWithData:data];
}];
}];
[self.navigationController.navigationBar setHidden:YES];
}
Thanks!

Resources