I can't seem to set a Pffile object as a value for a Pfobject key in Objective-C. I'm trying to save NSData from an AVAudioPlayer in a PFfile.
If I do the folllowing:
NSData * audioData=[self.shoutInfoArray objectAtIndex:1];
PFFile * audiofile=[PFFile fileWithName:#"shoutData" data:audioData];
bool saved=[audiofile save]; //This bool is positive, so it does save!?
[shout fetchIfNeeded];
shout[#"audioData"]=audiofile; //BUGGY LINE
I get the following error:
Error: invalid type for key audioData, expected bytes, but got file
(Code: 111, Version: 1.2.20)
Couldn't find why?
Clear your database. I mean drop column audioData. It seams something wrong with types.
To Save a PFFile object as a part of PFObject:Also check file size should not be greater than 10MB.
PFFile * audiofile=[PFFile fileWithName:#"shoutData.aif" data:audioData];
[imageFile saveInBackgroundWithBlock:^(BOOL succeeded, NSError *error) {
//Use async call.
// It is compulsory to save the PFFile object first and then used it with PFObject
if(succeeded)
{
PFObject *shout = [PFObject objectWithClassName:#"UserData"];
shout[#"audioData"] = audiofile;
[shout saveInBackgroundWithBlock:^(BOOL succeeded, NSError *error) {
if(error)
{
NSLog(#"error %#",error.localizedDescription);
}
else
{
if(succeeded)
{
NSLog(#"object save on parse");
}
}
}];
}
}];
Related
I am having a problem uploading images to Parse. Things were working fine up to yesterday. My app isn't live yet I'm just testing, images are about 25kb and it's just a single image used for the user profile picture. Code is:
//Save the image
NSData *imageData = UIImageJPEGRepresentation(image, 1);
PFFile *imageFile = [PFFile fileWithName:#"profile.jpg" data:imageData];
[imageFile saveInBackgroundWithBlock:^(BOOL succeeded, NSError *error) {
if(succeeded){
[userBank setObject:imageFile forKey:#"profilePic"];
[userBank saveInBackgroundWithBlock:^(BOOL succeeded, NSError *error) {
if(succeeded){
NSLog(#"save done");
userBank = [PFUser currentUser];
user[#"profilePic"] = imageFile;
[userBank saveInBackground];
}
else{
NSLog(#"%#", error);
handler(NO,YES,nil);
}
}];
}
else{
NSLog(#"image not saved %#",error);
handler(NO,YES,nil);
}
}];//End save image block
I am suddenly getting this error: request body stream exhausted, NSUnderlyingError=0x17ece150 "request body stream exhausted". Has anyone encountered this before and could give me some pointers to what might be happening here?
Try this:
NSData *imageData = UIImageJPEGRepresentation(image, 1);
PFFile *imageFile = [PFFile fileWithName:#"profile.jpg" data:imageData];
[imageFile saveInBackgroundWithBlock:^(BOOL succeeded, NSError *error) {
if (!error) {
if (succeeded) {
userBank = [PFUser currentUser];
user[#"profilePic"] = imageFile;
[userBank saveInBackground];
}
} else {
// Handle error
}
}];
Seems the issue was either my connection or Parse, although I did try and reset my internet connection a number of times and it made no difference. Anyway after about 30 minutes it started working again. Just posting this incase someone else has the same issue. Parse doesn't seem that reliable...
try this
This error Comes on IOS but you can use different approach
like change your code line in formdata where you appending the file
var fd = new FormData();
fd.append("fileToUpload", document.getElementById('fileToUpload').files[0]);
to the below line basically don't append the file control but use the base64 image data
var reader = new FileReader();
reader.readAsDataURL(opmlFile.files[0]);
reader.onload = function () {
var base64DataImg = reader.result;
base64DataImg = base64DataImg.replace('data:'imagetype';base64,', '');
formData.append("FileBase64Data", base64DataImg);
}
Regards
Anil
I am trying to download some short sound file on Parse.com in an iOS application.
The file has previously been saved using the following code:
NSData *soundData = [NSData dataWithContentsOfURL:myURL];
parse_Sound = [PFFile fileWithName:#"XXYYZZ"
data:soundData];
[parse_Sound saveInBackgroundWithBlock:^(BOOL succeeded, NSError *error) {
if (!succeeded) {
NSLog(#"sound-upload NG”);
} else {
NSLog(#"sound-upload OK");
}];
}
}];
Seeing the message on the debugging console, it appearently works.
Now what kind of code do I need to run to retrieve(download) the sound file?
I have browsed the net, but found nothing clear and working.
To get data back from the server you need to need to run a query asking for that object but you haven't associated the uploaded file with a column in any Class yet. Uploading a PFFile is iOS is a two step process:
1) Upload the PFFile to the server
2) In the callback associated the PFFile with a column in a data object
NSData *soundData = [NSData dataWithContentsOfURL:myURL];
parse_Sound = [PFFile fileWithName:#"XXYYZZ"
data:soundData];
[parse_Sound saveInBackgroundWithBlock:^(BOOL succeeded, NSError *error) {
if (!succeeded) {
NSLog(#"sound-upload NG”);
} else {
NSLog(#"sound-upload OK");
PFObject *soundStuff = [PFObject objectWithClassName:#"Sounds"];
soundStuff[#"soundFile"] = parse_Sound;
[soundStuff saveInBackground];
}];
}
}];
Now to get the data back you would run a query on the Sounds class that will have the sound data in the soundFile column:
PFQuery *query = [PFQuery queryWithClassName:#"Sounds"];
[query whereKey:#"someKey" equalTo:#"someValue"];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if (!error) {
// The find succeeded.
// Do something with the found objects
for (PFObject *object in objects) {
NSLog(#"%#", object.objectId);
PFFile *soundFile = object[#"soundFile"];
NSData *soundData = [soundFile getData];
}
} else {
// Log details of the failure
NSLog(#"Error: %# %#", error, [error userInfo]);
}
}];
I haven't tested any of this code but it at least demonstrates the steps needed and should get you started.
Here are the examples from the documentation:
PFObject *jobApplication = [PFObject objectWithClassName:#"JobApplication"]
jobApplication[#"applicantName"] = #"Joe Smith";
jobApplication[#"applicantResumeFile"] = file;
[jobApplication saveInBackground];
Then to get the data back:
PFFile *applicantResume = anotherApplication[#"applicantResumeFile"];
NSData *resumeData = [applicantResume getData];
Notice that file is being associated with the applicantResumeFile column of the JobApplication class so that the file data can be retrieved in queries.
You need to keep a reference to that file somewhere (ideally in a column of the PFObject it belongs to).
If you don't keep a reference you're out of luck and you can't retrieve already uploaded files that have no association to any object.
I suggest you read through the Parse documentation for files on iOS https://www.parse.com/docs/ios_guide#files/iOS
I am requesting a file representation of an NSDictionary from Parse.com (yes I know there are other more obvious ways to store dictionaries) and then in the completion block the data gets unarchived and assigned to a property.
When this code executes it never seems to return from the unarchive line. Nothing freezes, there is no error or exception. The app continues running as though everything is fine. If I set break points at the unarchiver line and the line after it, the first breakpoint gets hit but the second never does.
I can confirm that the function has returned the expected amount of data for this file.
PFFile *definitionFile = appObject[#"myFile"]; //PFFile reference from a PFObject
[definitionFile getDataInBackgroundWithBlock:^(NSData *data, NSError *error) {
if (!error) {
if (data) {
//A breakpoint on the following line does fire and show that there is data being given to the unarchiver
self.pendingDefinition = (NSDictionary *) [NSKeyedUnarchiver unarchiveObjectWithData:data];
}
//////Nothing beyond this point gets executed////////
[self handleNewDefinition];
} else {
NSLog(#"ERROR");
}
}];
As it turned out the data was being stored as a plist and I needed to use plist serialization to extract it:
if (data) {
NSError *error;
NSPropertyListFormat format;
NSDictionary* plist = [NSPropertyListSerialization propertyListWithData:data options:NSPropertyListImmutable format:&format error:&error];
if(!plist){
NSLog(#"Error: %#",error);
}
I am using Parse. I have a PFFILE that I am retrieving using a Query. I need to save it, and i found that you normally use saveEventualy. But it doesn't support PFFile. So how can I turn the PFFile into a PFObject? Or else how save the image for offline? That's my code up to now:
-(void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[self GetImage];
}
- (void)enteredForeground:(NSNotification*) not
{
[self GetImage];
}
-(void)GetImage
{
PFQuery *query = [PFQuery queryWithClassName:#"Image"];
[query getObjectInBackgroundWithId:#"4tmub1uxVd" block:^(PFObject *imageObject, NSError >*error)
{
if (imageObject) {
PFFile *imageFile = imageObject[#"image"];
[imageFile getDataInBackgroundWithBlock:^(NSData *data, NSError *error) {
if (data) {
UIImage *image = [UIImage imageWithData:data];
if (image) {
self.imageview.image = image;
}
} else {
NSLog(#"Error fetching image file: %#", error);
}
}];
} else {
NSLog(#"Error fetching object: %#", error);
}
}];
}
Parse has recently introduced a new method called local Data Store. It let's you store objects and files, update and retrieve them. Check out the documentation.
Blog Post
Documentation
That doesn't exactly answer your question, but it will achieve what you want it to!
You can't convert a PFFile to a PFObject, but you don't need to. The Image PFObject class you're fetching in the code above has a property, with key image, that represents a PFFile. If you modify this, you'd save the parent object, which would save the updated file alongside it.
I am trying to download images from Parse and when I am finished downloading all images from parse my program crashes with the error:
NSNull getDataInBackgroundWithBlock:progressBlock:]: unrecognized selector sent to instance.
I have tried adding some conditions such as
if(![object objectForKey:#"goal_image"]) //If it is nil => exit
But it is still crashing. Here is my code:
PFQuery *query = [PFQuery queryWithClassName:#"Goal"];
[query getObjectInBackgroundWithId:[object objectId] block:^(PFObject *object, NSError *error) {
if(!error)
{
PFFile * imageFile = [object objectForKey:#"goal_image"];
if (imageFile) {
[imageFile getDataInBackgroundWithBlock:^(NSData *data, NSError *error2) {
if (!error2) {
NSString *jpgPath = [NSHomeDirectory() stringByAppendingPathComponent:[NSString stringWithFormat:#"Images/Goals/%#",[object objectId]]];
[data writeToFile:jpgPath atomically:YES];
}
} progressBlock:^(int percentDone) {
if (percentDone == 100) {
NSLog(#"Download Completed");
}
}];
}
}
}];
tl;dr
You should check for NSNull aside from checking for nil.
PFFile * imageFile = object[#"goal_image"]; // note the modern Obj-C syntax
if (imageFile && ![image isEqual:[NSNull null]]) {
...
}
Explanation
NSNull is different from nil, the first one being an object.
Since NSArray and NSDictionary only hold objects, nil cannot be stored in such containers and that's why NSNull is used, typically to represent a null value returned in the JSON response.
Sending messages to nil fails silently, whereas sending an unrecognized selector to the NSNull singleton will result in a crash.
Also remember that objectForKey: will return nil in case the key is not found in the dictionary.
I know this is old, but just in case anyone else is having this problem. For me, the above answer didn't work. What worked for me was enabling local datastore in app delegate. Honestly, not sure why this works, but I thought I should share
// Enable Local Datastore
[Parse enableLocalDatastore];