I'm trying to save an image to parse.com with the following code:
NSData *imageData = UIImagePNGRepresentation(profileImage);
PFFile *imageFile = [PFFile fileWithName:#"Profileimage.png" data:imageData];
[imageFile saveInBackground];
PFUser *user = [PFUser currentUser];
user[#"fullName"] = name;
user[#"Location"] = location;
user[#"gender"] = gender;
user[#"email"] = email;
user[#"ProfilePic"] = imageFile;
[user saveInBackground];
The problem is that this doesn't seem to be saving the image file to parse as nothing is populated in my data browser. The code here looks fine to me, but can you guys see anything wrong with it?
The image is being downloaded from Facebook with the following code:
NSURL *pictureURL = [NSURL URLWithString:[NSString stringWithFormat:#"https://graph.facebook.com/%#/picture?type=large&return_ssl_resources=1", facebookID]];
NSData *data = [[NSData alloc] initWithContentsOfURL:pictureURL];
UIImage *profileImage = [[UIImage alloc] initWithData:data];
Any ideas?
Thanks
The problem is that the [imageFile saveInBackground]; operation has not yet been performed when you call [user saveInBackground];
When you call the first background save, the program just continues on.
Use saveInBackgroundWithBlock instead, and then do the [user saveInBackground] operation there.
NSData *imageData = UIImagePNGRepresentation(profileImage);
PFFile *imageFile = [PFFile fileWithName:#"Profileimage.png" data:imageData];
[imageFile saveInBackgroundWithBlock:^(BOOL succeeded, NSError *error) {
if (!error) {
if (succeeded) {
PFUser *user = [PFUser currentUser];
user[#"fullName"] = name;
user[#"Location"] = location;
user[#"gender"] = gender;
user[#"email"] = email;
user[#"ProfilePic"] = imageFile;
[user saveInBackground];
}
} else {
// Handle error
}
}];
Related
NSURL *pictureURL = [NSURL URLWithString:[NSString stringWithFormat:#"https://graph.facebook.com/%#/picture?type=large&return_ssl_resources=1", facebookID]];
NSString *urlString = [pictureURL absoluteString];
FBSDKGraphRequest *request = [[FBSDKGraphRequest alloc] initWithGraphPath:#"me" parameters:nil];
[request startWithCompletionHandler:^(FBSDKGraphRequestConnection *connection, id result, NSError *error) {
if (!error) {
// result is a dictionary with the user's Facebook data
NSDictionary *userData = (NSDictionary *)result;
NSString *facebookID = userData[#"id"];
NSURL *pictureURL = [NSURL URLWithString:[NSString stringWithFormat:#"https://graph.facebook.com/%#/picture?type=large&return_ssl_resources=1", facebookID]];
NSString *urlString = [pictureURL absoluteString];
NSLog(#"sting=%#",urlString);
PFUser *me = [PFUser currentUser];
me[#"facebookId"] = userData[#"id"];
me["pictureURL"] = userData[urlString];
me[#"username"] = userData[#"name"];
[me saveInBackgroundWithBlock:^(BOOL succeeded, NSError * _Nullable error) {
if (error) {
NSLog(#"Error to store=%#",error.localizedDescription);
}
}];
[self presentViewController:push animated:YES completion:nil];
} else {
[self presentViewController:push animated:YES completion:nil];
}
}];
I need to store the Facebook Image or URL when any new user login into my app. AFAIK we can't save the url directly so tried to convert it into NSString but then it threw error "'Can't use nil for keys or values on PFObject. Use NSNull for values.'"
Is there any way so that I can store that link or any other alternate way to save directly the Image into Parse?
Your issue is most likely being caused by the following line:
me["pictureURL"] = userData[urlString];
You most likely want this to be:
me["pictureURL"] = urlString;
As you have it, you will setting me[#"pictureURL"] to nil because you probably don't have a value in userData with a key matching urlString.
Try this, the url should be converted to data then saved as a PFFile.
NSURL *pictureURL = [NSURL URLWithString:[NSString stringWithFormat:#"https://graph.facebook.com/%#/picture? type=large&return_ssl_resources=1", facebookID]];
NSData *data = [NSData contentsOfURL:picureURL];
PFFile *file = [PFFile fileWithData:data];
//save it
[file saveInBackground];
Hope that helps!
I am using Parse.com
When I download my PFFile(contains image) in viewDidAppear my app freezes for a while and then it shows the pic. But that is not right. I want UIActivityIndicatorView to be animated or at least shown. I know that this deals with async or something. But I have no idea how to make that work correctly.
PFFile* imageFile = [[PFUser currentUser] objectForKey:#"profilePic"];
if (imageFile) {
self.activity.hidden = NO;
[self.activity startAnimating];
NSURL* imageFileUrl = [[NSURL alloc]initWithString:imageFile.url];
NSData* imageData = [NSData dataWithContentsOfURL:imageFileUrl];
self.profilePic.image = [UIImage imageWithData:imageData];
}
This downloads the image and shows it.
UPD:
PFQuery* query = [PFUser query];
[query valueForKey:#"profilePic"];
[query findObjectsInBackgroundWithBlock:^(NSArray* data, NSError* error)
{
PFFile* imageFile = data[0];
[imageFile getDataInBackgroundWithBlock:^(NSData* data,NSError* error){
if (!error) {
self.activity.hidden = NO;
[self.activity startAnimating];
NSURL* imageFileUrl = [[NSURL alloc]initWithString:imageFile.url];
NSData* imageData = [NSData dataWithContentsOfURL:imageFileUrl];
self.profilePic.image = [UIImage imageWithData:imageData];
}else{
self.profilePic.image = [UIImage imageNamed:#"profile#2.png"];
}
}];
}];
UPD 2:
This solved my problem. Both answers were helpful.
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);
}
}];
This is because you are not getting the object in the background. Try using a query to accomplish this. If you need more info I can give you the full query as I have this code inside my app :)
Sample code:
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {}];
To get an image with data:
PFFile *imageFile = [object objectForKey:#"YOURKEY"];
[imageFile getDataInBackgroundWithBlock:^(NSData *data, NSError *error) {}];
There are couple of things wrong with your code
Your query is not right, I can't understand this part [query valueForKey:#"profilePic"]; if you want to get user have profile pics then you should do something like this [query whereKeyExist:#"profilePic"];, but at the moment query you have will bring down all objects.
You are downloading image in main thread which make your app free you should do something like this
[imageFile getDataInBackgroundWithBlock:^(NSData *imageData, NSError *error) {
if (!error)
{
self.profilePic.image = [UIImage imageWithData:imageData];
}
}];
You must check data.count before calling data[0], this could crash your application if data array is nil or empty.
Update:
Getting profile pic for currentUser will be something like this
PFUser *currentUser = [PFuser currentUser];
if (!currentUser)
{
//need to login
}
else
{
// may be you need to fetch
__weak typeof(self) weakSelf = self;
[currentUser fetchIfNeededInBackgroundWithBlock:^(PFObject *obj, NSError *error){
PFFile* imageFile = [[PFUser currentUser] objectForKey:#"profilePic"];
[imageFile getDataInBackgroundWithBlock:^(NSData *imageData, NSError *error) {
if (!error)
{
weakSelf.profilePic.image = [UIImage imageWithData:imageData];
}
}];
}];
}
I was normally trying to load the image for each cell like so in my UITableView using Parse SDK:
PFRelation *relation = [object relationForKey:#"images"];
PFQuery *relationQuery = [relation query];
[relationQuery getFirstObjectInBackgroundWithBlock:^(PFObject *obj, NSError *error) {
if (!error)
{
// Adding Image to ImageView
if ([obj objectForKey:#"image"])
{
PFFile *image = (PFFile *)[obj objectForKey:#"image"];
[image getDataInBackgroundWithBlock:^(NSData *data, NSError *error){
if (error)
{
cell.carPhoto.image = [UIImage imageNamed:#"placeholder.png"];
}
else
{
UIImage *carImage = [UIImage imageWithData:data];
cell.carPhoto.image = carImage;
}
}];
}
else
{
cell.carPhoto.image = [UIImage imageNamed:#"placeholder.png"];
}
}
}];
The issues with that, is that it is using way too many queries and the cells have a little lag when scrolling and show the pic above for a brief second before the actual. I attempted to change my code to this to use SDWebImage:
PFRelation *relation = [object relationForKey:#"images"];
PFQuery *relationQuery = [relation query];
[relationQuery getFirstObjectInBackgroundWithBlock:^(PFObject *obj, NSError *error) {
if (!error)
{
// Adding Image to ImageView
if ([obj objectForKey:#"image"])
{
PFFile *image = (PFFile *)[obj objectForKey:#"image"];
NSString *theUrl = image.url;
NSLog(#"%#", theUrl);
[cell.carPhoto setImageWithURL:[NSURL URLWithString:[theUrl stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]]
placeholderImage:nil];
}
else
{
cell.carPhoto.image = [UIImage imageNamed:#"placeholder.png"];
}
}
}];
But now I keep getting: -[UIImageView setImageWithURL:placeholderImage:]: unrecognized selector sent to instance 0x7c04ab40. Basically my end goal is to have it so images aren't queried every time the tableView is scrolled, and are cached. Any ideas?
Taking Image:
I'm taking the image using the code in this question:
Scaling UIImage with a UIIImagePicker's CGAffineTransform and Saving to Parse SDK
Convert UIImage to NSData & Save
_imageData = UIImageJPEGRepresentation(_image, .1);
PFFile *imageFile = [PFFile fileWithName:#"image.png" data:_imageData];
newMessage[#"image"] = imageFile;
Problem:
When I redownload the data, the UIImage appears squished. When I look at the image on my database, it seems like the height and width are reversed. Not sure why this is happening...
NSData *imageData = UIImageJPEGRepresentation(yourImage, 1.0);
PFFile *imageFile = [PFFile fileWithName:#"Image.jpg" data:imageData];
PFObject *userPhoto = [PFObject objectWithClassName:#"Photo"];
[userPhoto setObject:imageFile forKey:#"image"];
// Set the access control list to current user for security purposes
userPhoto.ACL = [PFACL ACLWithUser:[PFUser currentUser]];
[userPhoto setObject:user forKey:#"user"];
[userPhoto saveInBackgroundWithBlock:^(BOOL succeeded, NSError *error) {
if (!error) {
NSLog(#"sucess");
}
else{
// Log details of the failure
NSLog(#"Error: %# %#", error, [error userInfo]);
}
[[ConnectionManager sharedManager] removeload];
}];
So I have the first class:
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
UIImage *chosenImage = info[UIImagePickerControllerOriginalImage];
self.imageView.image = chosenImage;
_camera_button.hidden = true;
_camera_imageview.hidden = false;
[_next_camera setEnabled:YES];
NSData *imageData = UIImagePNGRepresentation(chosenImage);
[self upload_selfie:imageData];
[picker dismissViewControllerAnimated:YES completion:NULL];
}
And I am wanting to transfer the variable: imageData to this class:
- (IBAction)upload_selfie:(NSData *)sender{
PFFile *imageFile = [PFFile fileWithName:#"Image.jpg" data:imageData];
// Save PFFile
[imageFile saveInBackgroundWithBlock:^(BOOL succeeded, NSError *error) {
if (!error) {
// Hide old HUD, show completed HUD (see example for code)
// Create a PFObject around a PFFile and associate it with the current user
PFObject *userPhoto = [PFObject objectWithClassName:#"UserPhoto"];
[userPhoto setObject:imageFile forKey:#"imageFile"];
// Set the access control list to current user for security purposes
userPhoto.ACL = [PFACL ACLWithUser:[PFUser currentUser]];
PFUser *user = [PFUser currentUser];
[userPhoto setObject:user forKey:#"user"];
[userPhoto saveInBackgroundWithBlock:^(BOOL succeeded, NSError *error) {
if (!error) {
// _loader6.hidden = true;
// [self performSegueWithIdentifier:#"toquestion" sender:self];
}
else{
// Log details of the failure
NSLog(#"Error: %# %#", error, [error userInfo]);
}
}];
}
}];
}
Where I have tried:
PFFile *imageFile = [PFFile fileWithName:#"Image.jpg" data:imageData];
But I receive the error "Use of undeclared identifier"?ces where I refrence imageData should I somewhere else?
Also these are the only two pla
Please may you explain why and what I can do about this?
You receive this error because your variable name is sender:
- (IBAction)upload_selfie:(NSData *)sender
You need change your code to:
PFFile *imageFile = [PFFile fileWithName:#"Image.jpg" data:sender];
PS. It seems that you use upload_selfie: method for two aims: a) interface builder action handler; b) method for saving photo. It is better to make two separate methods.
You're passing the parameter as sender so that's the name you should use: PFFile *imageFile = [PFFile fileWithName:#"Image.jpg" data:sender];.
Though, to be more understandable, choosing a different name would be good.