I'm trying to retrieve some text from a file that I uploaded to Parse, but anything that I try seems not to work. I tried using the example that Parse gave, but I couldn't make it work. Can somebody help or explain to me how I can do that?
This is the example:
PFFile *applicantResume = anotherApplication[#"applicantResumeFile"];
NSData *resumeData = [applicantResume getData];
Thanks
You need to convert the data back to a string, try this.
Save
PFObject * anotherApplication = [[PFObject alloc] initWithClassName:#"Resumes"];
NSData *data = [#"Working at Parse is great!" dataUsingEncoding:NSUTF8StringEncoding];
PFFile *file = [PFFile fileWithName:#"resume.txt" data:data];
anotherApplication[#"applicantResumeFile"] = file;
[anotherApplication save];
Open
[anotherApplication fetchIfNeeded];
PFFile *applicantResume = anotherApplication[#"applicantResumeFile"];
NSData *resumeData = [applicantResume getData];
NSString* dataStr = [[NSString alloc] initWithData:resumeData encoding:NSUTF8StringEncoding];
NSLog(#"Received string: %#", dataStr);
Don't forget that in practice, it's best to use 'getDataInBackgroundWithBlock:' , 'saveInBackgroundWithBlock:' , and 'fetchIfNeededInBackgroundWithBlock:'
A note on blocks:
NSLog(#"Will Run 1st: %#", reflex.description); // will be null
[applicantResume getDataInBackgroundWithBlock:^(NSData *data, NSError *error) {
NSString* dataStr = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
reflex.description = dataStr;
NSLog(#"Will Run 3rd: %#", reflex.description); // will contain string.
}];
NSLog(#"Will Run 2nd: %#", reflex.description); // will be null
PFFile *applicantResume = object[#"applicantResumeFile"];
NSData *resumeData = [applicantResume getData];
NSString* dataStr = [[NSString alloc] initWithData:resumeData encoding:NSUTF8StringEncoding];
reflex.description = dataStr;
It workы
When I use getData it doesnt
PFFile *applicantResume = object[#"applicantResumeFile"];
[applicantResume getDataInBackgroundWithBlock:^(NSData *data, NSError *error) {
if (!error) {
NSString* dataStr = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
reflex.description = dataStr;
}
}];
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 working on an app that will parse data from a Rest API. As I haven't done this before, I was wondering if NSScanner or NSRange would work for this. Here is an example using NSScanner for such purposes. It's a small string so it doesn't take much code, so it seemed like a quick and dirty option. Is there an easier and quicker way to do this?
- (void)GetAliasName:(NSString *)cno selector:(NSString*)selectorName completionHandler:(void (^)(NSDictionary *, NSError *))handler
{
NSMutableDictionary *d = [[NSMutableDictionary alloc] init];
[d setValue:interface forKey:#"interface"];
[d setValue:#"GetAlias" forKey:#"method"];
NSMutableDictionary *p = [[NSMutableDictionary alloc] init];
cno = [[NSUserDefaults standardUserDefaults] objectForKey:#"cno"];
[p setValue:cno forKey:#"cno"];
[p setValue:selectorName forKey:#"selector"];
[d setValue:p forKey:#"parameters"];
NSData *data = [NSJSONSerialization dataWithJSONObject:d options:0 error:nil];
[self load:data completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
NSLog(#"done");
NSString *s = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog(#"GetAlias RAW response = %#", s);
if (apiConditions)
{
dispatch_async(dispatch_get_main_queue(),
^{
[hud hide:YES];
[MBProgressHUD hideHUDForView:self.view animated:YES];
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Error" message:#"No network connection or no data found" delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alert show];
NSLog(#"data is NIL");
});
}
else
{
NSDictionary *d = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
handler(d, error);
//scans for aliasname
NSString *match = #"AliasName\": \"";
NSString *preTel;
NSString *postTel;
NSScanner *scanner = [NSScanner scannerWithString:s];
[scanner scanUpToString:match intoString:&preTel];
[scanner scanString:match intoString:nil];
postTel = [s substringFromIndex:scanner.scanLocation];
//removes newlines, characters, and whitespaces from aliasname
NSCharacterSet *trim = [NSCharacterSet characterSetWithCharactersInString:#"}]\""];
postTel = [[postTel componentsSeparatedByCharactersInSet: trim] componentsJoinedByString: #""];
postTel = [[postTel componentsSeparatedByCharactersInSet: [NSCharacterSet whitespaceAndNewlineCharacterSet]] componentsJoinedByString: #""];
NSLog(#"postTel: %#", postTel);
NSString *docno = [[NSUserDefaults standardUserDefaults] objectForKey:#"docno"];
//if docno is filled in, look up TR by docno
if ([docno isEqual: #""])
{
[self GetTR:(NSString*)postTel customStatus:customStatus completionhandler:^(NSDictionary *dictionary, NSError *error) {
nil;
}];
}
}];
}
There is NSJSONSerialization which is built for this.
Use it as follows:
NSError *error = nil;
NSDictionary *dictionary = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error];
NSString *aliasName = dictionary[#"AliasName"];
Edit
Since you already use this, and have dictionary, the only step you needed was to access dictionary with needed key(last step).
I'm really scratching my head at this one. I'm using the Pocket API to allow users to archive Pocket articles from my app, but whenever I try to do so with the below code I get this error:
Error Domain=PocketSDK Code=400 "Invalid request, please refer to API documentation" UserInfo=0xc17d3b0 {NSLocalizedDescription=Invalid request, please refer to API documentation}
Code:
NSDictionary *arguments = #{#"action": #"archive",
#"item_id": articleID};
[[PocketAPI sharedAPI] callAPIMethod:#"send" withHTTPMethod:PocketAPIHTTPMethodPOST arguments:arguments handler:^(PocketAPI *api, NSString *apiMethod, NSDictionary *response, NSError *error) {
if (!error) {
NSLog(#"Archived article.");
}
}];
Exactly what part of that is incorrect? Am I not POSTing a send method to the API?
EDIT: I even changed it to have #"action" be #"actions" and to supply it the above NSDictionary, and it returns without an error but doesn't affect it on the Pocket website...
EDIT 2: Per the response of Joseph Chen I changed my code to the following:
// Create data to pass to the Pocket API (a JSON array of actions)
NSError *error;
NSArray *actions = #[#{#"action": #"archive",
#"item_id": articleID}];
NSData *actionsAsJSONData = [NSJSONSerialization dataWithJSONObject:actions options:kNilOptions error:&error];
NSString *actionsAsJSONString = [[NSString alloc] initWithData:actionsAsJSONData encoding:NSUTF8StringEncoding];
NSDictionary *arguments = #{#"actions": actionsAsJSONString};
[[PocketAPI sharedAPI] callAPIMethod:#"send" withHTTPMethod:PocketAPIHTTPMethodPOST arguments:arguments handler:^(PocketAPI *api, NSString *apiMethod, NSDictionary *response, NSError *error) {
if (!error) {
NSLog(#"%#", response);
}
else {
NSLog(#"%#", error);
}
}];
Which returns:
action_results" = (
1
);
status = 1;
Yet when I go to the website and log in, the article I "archived" is still staring me in the face, unarchived.
According to the documentation the actions parameter should be a JSON dictionary. So you could either...
Create the JSON dictionary manually:
NSString *jsonString = [NSString stringWithFormat:#"[{\"action\":\"archive\",\"item_id\":\"%#\"}]", articleID]; // articleID is a NSString?
NSDictionary *arguments = #{#"actions": jsonString};
Use NSJSONSerialization:
NSDictionary *actions = #{#"action": #"archive", #"item_id": articleID};
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:actions
options:kNilOptions
error:&error];
NSString *jsonString = [[NSString alloc] initWithData:jsonData
encoding:NSUTF8StringEncoding];
NSDictionary *arguments = #{#"actions": jsonString};
This answer is also a reference.
Here's the code taken (almost) straight from my app:
NSTimeInterval timestamp = [[NSDate date] timeIntervalSince1970];
NSDictionary *arguments = #{#"actions" : #[#{#"action" : #"archive",
#"item_id" : itemId,
#"time" : [NSString stringWithFormat:#"%ld", (long)timestamp]}]};
[self.pocketAPI callAPIMethod:#"send"
withHTTPMethod:PocketAPIHTTPMethodPOST
arguments:arguments
handler:^(PocketAPI *api, NSString *apiMethod, NSDictionary *response, NSError *error)
{
if (!error) {
// OK
} else {
// handle error
}
}];
In my iOS app I've to parse a JSON file. From this JSON I need the following stuff: name, image width and image height. To get image name I'ven't any problem, to get image with and height I use the following code:
- (void) loadImageFromWeb:(NSString *)urlImg forName:(NSString*)name {
NSURL* url = [NSURL URLWithString:urlImg];
//NSURLRequest* request = [NSURLRequest requestWithURL:url];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url];
NSString *authCredentials =#"reply:reply";
NSString *authValue = [NSString stringWithFormat:#"Basic %#",[authCredentials base64EncodedStringWithWrapWidth:0]];
[request setValue:authValue forHTTPHeaderField:#"Authorization"];
[NSURLConnection sendAsynchronousRequest:request
queue:[NSOperationQueue mainQueue]
completionHandler:^(NSURLResponse * response,
NSData * data,
NSError * error) {
if (!error){
UIImage* image = [[UIImage alloc] initWithData:data];
imageWidth = image.size.width;
imageHeight = image.size.height;
imgWidth = [NSString stringWithFormat:#"%f", imageWidth];
imgHeight = [NSString stringWithFormat:#"%f", imageHeight];
self.dictWithDataForPSCollectionView = #{#"title": name,
#"width": imgWidth,
#"height": imgHeight};
[self.arrayWithData addObject:self.dictWithDataForPSCollectionView];
NSLog(#"DATA ARRAY: %#", self.arrayWithData);
} else {
NSLog(#"ERRORE: %#", error);
}
}];
}
You can see that I save the name, image width and image height in a NSDictionary then I put this in an NSMutableArray. When it execute the NSLog, I see this:
DATA ARRAY: (
{
height = "512.000000";
title = "Eau de Toilet";
width = "320.000000";
},
{
height = "1049.000000";
title = "Eau de Toilet";
width = "1405.000000";
}
)
My question is how to get this information back in the class who call my json parser, I tried to access to the variable in this way:
-(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
recivedData = [[NSMutableData alloc]init];
}
-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
[recivedData appendData:data];
NSString *string = [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding];
NSLog(#"JSON: %#", string);
}
-(void)connectionDidFinishLoading:(NSURLConnection *)connection
{
NSDictionary *json;
NSError *err;
json = [NSJSONSerialization JSONObjectWithData:recivedData options:NSJSONReadingMutableLeaves error:&err];
JsonCategoryReader *reader = [[JsonCategoryReader alloc]init];
[reader parseJson:json];
}
But when I run the code it shows me an empty array. How I can have the information in this class?
UPDATE:
The JSON I've to parse is the following:
{
"1":{
"entity_id":"1",
"type_id":"simple",
"sku":"EAU_DE_TOILET_1",
"description":"A passionate scent with the zest of exclusive Zegna Bergamot, sparked by Violettyne Captive, and the warmth of Vetiver and Cedarwood",
"short_description":"EAU DE TOILETTE NATURAL SPRAY",
"meta_keyword":null,
"name":"Eau de Toilet",
"meta_title":null,
"meta_description":null,
"regular_price_with_tax":60,
"regular_price_without_tax":60,
"final_price_with_tax":60,
"final_price_without_tax":60,
"is_saleable":true,
"image_url":"http:\/\/54.204.6.246\/magento8\/media\/catalog\/product\/cache\/0\/image\/9df78eab33525d08d6e5fb8d27136e95\/p\/r\/product_100ml.png"
},
"2":{
"entity_id":"2",
"type_id":"simple",
"sku":"EAU_DE_TOILET_2",
"description":"A passionate scent with the zest of exclusive Zegna Bergamot, sparked by Violettyne Captive, and the warmth of Vetiver and Cedarwood",
"short_description":"EAU DE TOILETTE NATURAL SPRAY",
"meta_keyword":null,
"name":"Eau de Toilet",
"meta_title":null,
"meta_description":null,
"regular_price_with_tax":60,
"regular_price_without_tax":60,
"final_price_with_tax":60,
"final_price_without_tax":60,
"is_saleable":true,
"image_url":"http:\/\/54.204.6.246\/magento8\/media\/catalog\/product\/cache\/0\/image\/9df78eab33525d08d6e5fb8d27136e95\/s\/c\/scheda_non_shop.jpg"
}
}
My method parseJson do the following:
- (void)parseJson:(NSDictionary *)jsonDict {
// Controllo che il json sia stato ricevuto
if (jsonDict) {
self.nameArray = [[NSMutableArray alloc]init];
self.imgUrlArray = [[NSMutableArray alloc]init];
self.dictWithDataForPSCollectionView = [[NSDictionary alloc]init];
self.arrayWithData = [[NSMutableArray alloc]init];
[self createArrayWithJson:jsonDict andIndex:1];
[self createArrayWithJson:jsonDict andIndex:2];
}
- (void)createArrayWithJson:(NSDictionary*)json andIndex:(NSString*)i {
NSDictionary *products = [json objectForKey:i];
NSString *name = [products objectForKey:#"name"];
NSString *imgUrl = [products objectForKey:#"image_url"];
// Scarico l'immagine e calcolo le dimensioni
if (name != nil && imgUrl != nil) {
[self loadImageFromWeb:imgUrl forName:name];
}
}
I hope you understand what I did
what happen is that your class is make before that your json is download, for have a good sequence you have to call your method for parse the json inside the completionHandler block, when you are sure that it is download. then when you have your object load you can parse it like this example:
for (NSDictionary *dic in reader.arrayWithData){
NSLog("height: %#",[dic objectForKey:#"height"]);
NSLog("title: %#",[dic objectForKey:#"title"]);
NSLog("width: %#",[dic objectForKey:#"width"]);
}
I have a NSDictionary called itemDict and when printing
NSLog(#"itemDictValues:%#",itemDict);
The output is in this format:
itemDictValues:
GTLPlusPerson 0xab821e0:
{etag:""LTv_6IJISeUQGTVXLjMeOtebkoM/eup2crXcelmpMFKesXWlGkJjCiE"" kind:"plus#person" id:"1145282979128841" objectType:"person" displayName:"FirstName LastName" image:{url} url:"https://plus.google.com/1145282979128841"}
From this I need to extract the values corresponding to id, displayName and url to my NSString variables, in this format
profileId=1145282979128841;
Name=FirstName LastName;
Profilepic=https://plus.google.com/1145282979128841;
How do I go about this?
try this ...
_profileId=(NSString*)((GTLPlusPerson*)itemDict).identifier;
_profileName= (NSString*)((GTLPlusPerson*)itemDict).displayName;
_profileImageURLPath=(NSString*)((GTLPlusPerson*)itemDict).image.url;
You just parse the Dictionary to get your desired information.
NSString *profileId = [itemDict objectForKey:#"id"];
NSString *displayName = [itemDict objectForKey:#"displayName"];
Now that image, I think that's in a dictionary itself. And since you haven't specified what's inside that dictionary, so here's what I think you should do:
NSDictionary *imageDict = [itemDict objectForKey:#"image"];
NSURL *imageURL = [imageDict objectForKey:#"url"];
Then getting the UIImage becomes pretty straightforward :
NSURLRequest *request = [[NSURLRequest alloc] initWithURL:imageURL];
NSData *imageData = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];
UIImage *image = [[UIImage alloc] initWithData:imageData];
You should choose the sendAsynchronousRequest method as it happens in the background and doesn't hold up the functionality of your app.
For an NSDictionary
NSString *profileId = itemDict[#"id"]
NSString *name = itemDict[#"displayName"]
NSString *profilePic = itemDict[#"image"][#"url"]
If it is GTLPlusPerson object then access the properties with objective-c dot syntax
NSString *profileId = itemDict.id;
NSString *name = itemDict.displayName;
NSString *profilePic = itemDict.url;
Judging by your log, it appears it is a GTLPlusPerson object and not an NSDictionary
NSArray* peopleList = peopleFeed.items;
NSLog(#"peopleList %# ",peopleList.description);
for (NSArray *dict in peopleFeed.items) {
NSString *peopleStrID=(NSString*)((GTLPlusPerson*)dict).identifier;
NSLog(#"peopleStrID %#",peopleStrID);
NSString *peopleName = (NSString*)((GTLPlusPerson*)dict).displayName;
NSString *peoplePic = (NSString*)((GTLPlusPerson*)dict).image.url;
}
The easiest way is to use the code Google provides:
if ([[GPPSignIn sharedInstance] authentication]) {
// The user is signed in.
GTLQueryPlus *query = [GTLQueryPlus queryForPeopleGetWithUserId:#"me"];
GTLServicePlus* plusService = [[GTLServicePlus alloc] init];
plusService.retryEnabled = YES;
//auth = GTMOAuth2Authentication object from login
[plusService setAuthorizer:auth];
[plusService executeQuery:query
completionHandler:^(GTLServiceTicket *ticket,
GTLPlusPerson *person,
NSError *error) {
if (error) {
GTMLoggerError(#"Error: %#", error);
} else {
// Retrieve the display name and "about me" text
NSString *description = [NSString stringWithFormat:#"%#\n%#", person.displayName, person.aboutMe];
NSString *imageURL = person.image.url;
}
}];
} else {
//user is logged out
}
}