Save hundreds of PFObjects to Parse cloud - ios

I have an application where I have two parse tables - "User" and "Topics". Now what I want is that if any user signs up, then I want to create another parse table which will store some info related to that user and the topic say topic progress. Here's my code -
- (IBAction)signUpFunction {
[self.view endEditing:YES];
NSString *fullName = self.nameTextField.text;
NSString *username = self.usernameTextField.text;
NSString *password = self.passwordTextField.text;
NSString *email = self.emailTextField.text;
if ([username length] == 0 || [password length] == 0 || [email length] == 0 || [fullName length] == 0)
{
[[[UIAlertView alloc] initWithTitle:#"Missing Information"
message:#"Make sure you fill out all of the information!"
delegate:nil
cancelButtonTitle:#"ok"
otherButtonTitles:nil] show];
}
else {
PFUser *newUser = [PFUser user];
newUser.username = username;
newUser.password = password;
newUser.email = email;
newUser[#"fullName"] = fullName;
[newUser signUpInBackgroundWithBlock:^(BOOL succeeded, NSError *error) {
if (error) {
[[[UIAlertView alloc] initWithTitle:#"Error!"message:[error.userInfo objectForKey:#"error"] delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil] show ];
}
else
{
PFQuery *topicsQuery = [PFQuery queryWithClassName:#"Topic"];
[topicsQuery findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if (error) {
NSLog(#"Error: %# %#", error, [error userInfo]);
}
else {
for (unsigned int i = 0; i < objects.count; i++) {
PFObject *object = objects[i];
PFObject *topicProgressForUser = [PFObject objectWithClassName:#"QuizProgress"];
[topicProgressForUser setObject:[PFUser currentUser] forKey:#"user"];
[topicProgressForUser setObject:object forKey:#"topic"];
if ([object[#"fullAccess"] isEqualToString:#"Yes"]) {
[topicProgressForUser setObject:#"Free" forKey:#"purchased"];
} else {
[topicProgressForUser setObject:#"No" forKey:#"purchased"];
}
[topicProgressForUser setObject:0 forKey:#"questionsSolved"];
[topicProgressForUser setObject:0 forKey:#"attempts"];
[topicProgressForUser setObject:0 forKey:#"resultInPercentage"];
[topicProgressForUser setObject:#"Basic" forKey:#"achievement"];
[topicProgressForUser setObject:NO forKey:#"generateCertificate"];
[topicProgressForUser saveEventually];
}
}
}]; // topic block
}
}]; // signup block
}
}
I don't think I am using the right standard of saving data to parse cloud by saving each pfobject individually. What if the internet connection is lost in the middle of saving objects ? Can anyone help me in using the correct and fast approach of saving multiple pfobject data to new table in parse cloud.

In your case, I would take a look at the class methods saveAll, saveAllInBackground, etc.
I took your code and modified it how I think makes the most sense in this case. Let me know if it works:
- (IBAction)signUpFunction {
[self.view endEditing:YES];
NSString *fullName = self.nameTextField.text;
NSString *username = self.usernameTextField.text;
NSString *password = self.passwordTextField.text;
NSString *email = self.emailTextField.text;
if ([username length] == 0 || [password length] == 0 || [email length] == 0 || [fullName length] == 0) {
[[[UIAlertView alloc] initWithTitle:#"Missing Information"
message:#"Make sure you fill out all of the information!"
delegate:nil
cancelButtonTitle:#"ok"
otherButtonTitles:nil] show];
} else {
PFUser *newUser = [PFUser user];
newUser.username = username;
newUser.password = password;
newUser.email = email;
newUser[#"fullName"] = fullName;
[newUser signUpInBackgroundWithBlock:^(BOOL succeeded, NSError *error) {
if (error) {
[[[UIAlertView alloc] initWithTitle:#"Error!"message:[error.userInfo objectForKey:#"error"] delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil] show ];
} else {
PFQuery *topicsQuery = [PFQuery queryWithClassName:#"Topic"];
[topicsQuery findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if (error != nil) {
NSLog(#"Error: %# %#", error, [error userInfo]);
} else {
NSMutableArray *topics = [NSMutableArray array];
for (unsigned int i = 0; i < objects.count; i++) {
PFObject *object = objects[i];
PFObject *topicProgressForUser = [PFObject objectWithClassName:#"QuizProgress"];
[topics addObject:topicProgressForUser];
topicProgressForUser[#"user"] = [PFUser currentUser];
topicProgressForUser[#"topic"] = object;
topicProgressForUser[#"questionSolved"] = #(NO);
topicProgressForUser[#"attempts"] = #(0);
topicProgressForUser[#"resultInPercentage"] = #(0);
topicProgressForUser[#"achievement"] = #"Basic";
topicProgressForUser[#"generateCertificate"] = #(NO);
if ([object[#"fullAccess"] isEqualToString:#"Yes"]) {
topicProgressForUser[#"purchased"] = #"Free";
} else {
topicProgressForUser[#"purchased"] = #"No";
}
}
[PFObject saveAllInBackground:objects block:^(BOOL succeeded, NSError *error) {
if (error != nil) {
// Do something here to handle the error
} else {
//
}
}
]; // saveAllInBackground
}
}]; // topic block
}
}]; // signup block
}
}

Change the below line of code:
[topicProgressForUser saveEventually];
to
[topicProgressForUser saveInBackground];
Hope this helps..

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");
}
}

Parse - Facebook users being recreated everytime

I'm using Parse.com + Facebook user and I'm noticing something unusual that has not been happening previously. A user creates an account via Facebook, logs in, logs out, logs in, logs out, and then when they try logging in, that user gets deleted and another user gets created. Why could that be?
Here is my signup/signin code:
-(IBAction)facebookSignIn:(id)sender{
CLGeocoder *geo = [[CLGeocoder alloc] init];
if(![CLLocationManager locationServicesEnabled] || [CLLocationManager authorizationStatus] == kCLAuthorizationStatusDenied ){
UIAlertView *locationAlert = [[UIAlertView alloc]initWithTitle:#"Oops!" message:#"You must have location services enabled for this app to work properly" delegate:self cancelButtonTitle:nil otherButtonTitles:#"Okay", nil];
[locationAlert show];
}else{
[PFFacebookUtils logInWithPermissions:_permissions block:^(PFUser *aUser, NSError *suError) {
if(!aUser){
NSLog(#"not fbook user because %#",[suError description]);
if([[[suError userInfo] objectForKey:#"com.facebook.sdk:ErrorLoginFailedReason"] isEqualToString:#"com.facebook.sdk:SystemLoginDisallowedWithoutError"]){
UIAlertView *alert = [[UIAlertView alloc]initWithTitle:#"Error" message:#"Looks like you have Facebook authentication disabled! Go to Settings > Facebook > mySwapp and turn the switch ON"delegate:nil cancelButtonTitle:nil otherButtonTitles:#"Okay", nil];
[alert show];
}
else{
UIAlertView *alert = [[UIAlertView alloc]initWithTitle:#"Error Signing In/Logging In" message:[suError localizedDescription] delegate:nil cancelButtonTitle:nil otherButtonTitles:#"Okay", nil];
[alert show];
}
}
else if(aUser.isNew){
NSLog(#"User is NEW");
[[FBRequest requestForMe] startWithCompletionHandler:
^(FBRequestConnection *connection,
NSDictionary<FBGraphUser> *user,
NSError *fbError) {
if (!fbError) {
NSLog(#"Facebook Request succeeded");
NSString *email = [user objectForKey:#"email"];
[aUser setEmail:email];
PFQuery *g = [PFQuery queryWithClassName:#"Counter"];
PFObject *cool = [g getObjectWithId:#"gpKDgNhwhw"];
[cool incrementKey:#"users"];
[cool saveEventually];
NSString *username = [NSString stringWithFormat:#"blahblah%d",[[cool objectForKey:#"users"] intValue]];
[aUser setUsername:username];
PFInstallation *installation = [PFInstallation currentInstallation];
[installation setObject:aUser forKey:#"user"];
[aUser setObject:#NO forKey:#"text"];
[aUser setObject:#YES forKey:#"snew"];
[aUser setObject:#"All" forKey:#"prefState"];
[aUser setObject:#"All" forKey:#"prefCat"];
[aUser setObject:#YES forKey:#"fnew"];
_type = #"facebook";
NSLog(#"Right before geopoint search....");
[PFGeoPoint geoPointForCurrentLocationInBackground:^(PFGeoPoint *geoPoint, NSError *error) {
if(!error){
NSLog(#"Got current geopoint!");
CLLocation *myLocation = [[CLLocation alloc]initWithLatitude:geoPoint.latitude longitude:geoPoint.longitude];
[geo reverseGeocodeLocation:myLocation completionHandler:^(NSArray *placemarks, NSError *error) {
if(!error){
CLPlacemark *pl = placemarks[0];
NSString *zip = [pl.addressDictionary objectForKey:(NSString *)kABPersonAddressZIPKey];
NSString *city = [pl.addressDictionary objectForKey:(NSString *)kABPersonAddressCityKey];
NSString *state = [pl.addressDictionary objectForKey:(NSString *)kABPersonAddressStateKey];
if(city == nil ||state ==nil){
NSLog(#"city or state is nil");
if(city==nil){
NSLog(#"city is nil");
}
if(state==nil){
NSLog(#"state is nil");
}
}
[aUser setObject:city forKey:#"city"];
[aUser setObject:state forKey:#"state"];
[aUser setObject:zip forKey:#"zip"];
[aUser setObject:geoPoint forKey:#"geopoint"];
[aUser setObject:#NO forKey:#"pref"];
[aUser setObject:#20 forKey:#"radius"];
[aUser setObject:#0 forKey:#"postCount"];
[aUser saveInBackgroundWithBlock:^(BOOL succeeded, NSError *perror) {
if(!perror && succeeded){
[self performSegueWithIdentifier:#"registerMe" sender:self]; }
else{
CCAlertView *errorAlert = [[CCAlertView alloc]initWithTitle:#"Oops!" message:[NSString stringWithFormat:#"%#. If you have already registered, please login regularly and go to the settings tab and switch on \"Link to Facebook\".",[[perror userInfo] objectForKey:#"error"]]];
[errorAlert addButtonWithTitle:#"Okay" block:^{
[aUser deleteInBackground];
}];
[errorAlert show];
}
}];
}
else{
CCAlertView *errorAlert = [[CCAlertView alloc]initWithTitle:#"Error getting Facebook data" message:[[fbError userInfo] objectForKey:#"error"]];
[errorAlert addButtonWithTitle:#"Okay" block:^{
[aUser deleteInBackground];
}];
[errorAlert show];
}
}];
}
else{
CCAlertView *errorAlert = [[CCAlertView alloc]initWithTitle:#"Facebook Sign In/Sign Up" message:[[suError userInfo] objectForKey:#"error"]];
[errorAlert addButtonWithTitle:#"Okay" block:^{
[aUser deleteInBackground];
}];
[errorAlert show];
NSString *ciid = [[PFInstallation currentInstallation] objectId];
[PFCloud callFunctionInBackground:#"logError" withParameters:#{#"installation":ciid,#"message":[suError description],#"place":#"Facebook Sign In/Sign Up"} block:^(id object, NSError *error) {
if(error){
PFObject * errorObj = [PFObject objectWithClassName:#"Error"];
[errorObj setObject:ciid forKey:#"installation"];
[errorObj setObject:[suError description] forKey:#"message"];
[errorObj setObject:#"Facebook Sign In/Sign Up" forKey:#"place"];
[errorObj saveEventually];
}
}];
}
}];
}
}];
}
else{
NSLog(#"User is OLD");
[self performSegueWithIdentifier:#"showMain" sender:self]; }
}];
}
}
and here is my logout code:
- (IBAction)goBackNow:(id)sender {
NSLog(#"gobacknow called");
[PFUser logOut];
[self.navigationController popToRootViewControllerAnimated:YES];
}
You can try to add more stuff to logout method. e.g.
[FBSession.activeSession closeAndClearTokenInformation];
[FBSession.activeSession close];
[FBSession setActiveSession:nil];
PFInstallation *installation = [PFInstallation currentInstallation];
installation[#"user"] = [NSNull null];
[installation saveInBackground];
Also remember to [installation saveInBackground]; in your example

STTwitter Not Returning Anything Neither Success or Error

I am having a very hard time here. There is one part in my application that STTwitter is successful and there is another part (using the same code) that does not return anything.
The part that does NOT work: `
-(IBAction)followTwitter:(id)sender {
if ([[NSUserDefaults standardUserDefaults] objectForKey:#"twitter_on_file" ] == nil) {
UIAlertView *allert = [[UIAlertView alloc] initWithTitle:#"Uh oh!" message:#"You have not linked your twitter account quite yet! Head to My Account settins to do so." delegate:nil cancelButtonTitle:#"Okay" otherButtonTitles:nil, nil];
[allert show];
} else {
ACAccountStore *store1 = [[ACAccountStore alloc] init];
ACAccountType *twitterAccountType = [store1 accountTypeWithAccountTypeIdentifier:ACAccountTypeIdentifierTwitter];
if ([twitterAccountType accessGranted]) {
[store1 requestAccessToAccountsWithType:twitterAccountType options:nil completion:^(BOOL granted, NSError *error) {
arrayOfUsernames = [[NSMutableArray alloc] init];
iosAccounts = [store1 accountsWithAccountType:twitterAccountType];
for (ACAccount *accou in iosAccounts) {
[arrayOfUsernames addObject:accou.username];
}
NSString *usernameOnFile = [[NSUserDefaults standardUserDefaults] objectForKey:#"twitter_on_file" ];
int tracker = 0;
for (NSString *username in arrayOfUsernames) {
if ([username isEqualToString:usernameOnFile]) {
NSLog(#"Using twitter account: %#", username);
STTwitterAPI *twitterAPI = [STTwitterAPI twitterAPIOSWithAccount:iosAccounts[tracker]];
[twitterAPI verifyCredentialsWithSuccessBlock:^(NSString *username) {
NSLog(#"Successfully authenticated the user");
} errorBlock:^(NSError *error) {
NSLog(#"Erorr: %#", error);
}];
NSLog(#"Twitter API: %#", twitterAPI);
[twitterAPI postFriendshipsCreateForScreenName:#"kickscaterer" orUserID:nil successBlock:^(NSDictionary *befriendedUser) {
NSLog(#"Befriend %#", befriendedUser);
} errorBlock:^(NSError *error) {
NSLog(#"Error: %#", error);
}];
} else {
tracker++;
}
}
}];
}
}
}
`
The part that DOES work:
STTwitterAPI *twitter= [STTwitterAPI twitterAPIOSWithAccount:iosAccounts[indexForAlert.row]];
[twitter verifyCredentialsWithSuccessBlock:^(NSString *username) {
// ...
NSLog(#"Username: %#", username);
// [self.tableView reloadData];
[[NSUserDefaults standardUserDefaults] setObject:twitter.userName forKey:#"twitter_on_file"];
} errorBlock:^(NSError *error) {
NSLog(#"Error: %#", error);
// ...
}];
[twitter postFriendshipsCreateForScreenName:#"didi4" orUserID:nil successBlock:^(NSDictionary *befriendedUser) {
NSLog(#"Befriend %#", befriendedUser);
} errorBlock:^(NSError *error) {
NSLog(#"Error: %#", error);
}];
Thanks!
The postFriendshipsCreateForScreenName: method should be called inside the success block, at the same level than the log "Successfully authenticated the user".

How to get User Image from class "User" in UIImageView? Parse.com

I want to download the image in a UIImageView user from Parse. In the User section, I created the UserImage section, but I can not download it into UIImageView, what should I do? You give me a hand? Help me please.
I've used this code:
PFUser* currentUser = [PFUser currentUser];
if (currentUser) {
PFQuery* queryPhoto = [PFQuery queryWithClassName:#"UserImage"];
[queryPhoto findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
// Verify if there are no errors
if (!error) {
// Retrieve Usename
User.text = [NSString stringWithFormat:#"%#",[[PFUser currentUser]valueForKey:#"username"]] ;
// Retrieve Photo
PFUser *currentuser = [PFUser currentUser];
PFFile *file = [currentuser objectForKey:#"UserImage"];
[file getDataInBackgroundWithBlock:^(NSData *data, NSError *error) {
if (!error) {
UIImage *image = [UIImage imageWithData:data];
// image can now be set on a UIImageView
self.UserImages.image = image;
}
}];
}
else {
NSString *errorString = [[error userInfo] objectForKey:#"error"];
UIAlertView *errorAlertView = [[UIAlertView alloc] initWithTitle:#"Error" message:errorString delegate:nil cancelButtonTitle:#"Ok" otherButtonTitles:nil, nil];
[errorAlertView show];
}
} ];
}
Parse.com has the PFImageView specifically to make this task eaiser.
Try this:
PFUser* currentUser = [PFUser currentUser];
if (currentUser) {
PFQuery* queryPhoto = [PFQuery queryWithClassName:#"UserImage"];
[queryPhoto findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
// Verify if there are no errors
if (!error) {
// Retrieve Usename
User.text = [NSString stringWithFormat:#"%#",[[PFUser currentUser]valueForKey:#"username"]] ;
// Retrieve Photo & Load
PFFile *file = [currentUser objectForKey:#"UserImage"];
PFImageView *imageView = [[PFImageView alloc] init];
self.UserImages.image = imageView; //Assuming here that you set self.UserImages.image as a PFImageView
self.UserImages.image.file = file;
[self.UserImages.image loadInBackground];
}
else {
NSString *errorString = [[error userInfo] objectForKey:#"error"];
UIAlertView *errorAlertView = [[UIAlertView alloc] initWithTitle:#"Error" message:errorString delegate:nil cancelButtonTitle:#"Ok" otherButtonTitles:nil, nil];
[errorAlertView show];
}
}];
}

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