I have a URL that returns a pretty flat XML file: <entries><title>val1</title><author>Bob</author></entries> The code runs ok:
NSString *urlString = [NSString stringWithFormat:#"http://www.somesite.php?qid=%d", __inum];
NSLog(#"urlString = %#", urlString);
NSURLResponse * response = nil;
NSError * error = nil;
NSURLRequest * urlRequest = [NSURLRequest requestWithURL: [NSURL URLWithString:urlString]];
NSData * myData = [NSURLConnection sendSynchronousRequest:urlRequest returningResponse:&response error:&error];
NSLog(#"%#", myData);
TBXML *sourceXML = [[TBXML alloc] initWithXMLData:myData error:nil];
TBXMLElement *rootElement = sourceXML.rootXMLElement;
if (rootElement) {
NSLog(#"Root element found...");
TBXMLElement *qaElement1 = [TBXML childElementNamed:#"title" parentElement:rootElement];
if (qaElement1) {
NSString *idAttribute = [TBXML valueOfAttributeNamed:#"title" forElement:qaElement1];
NSLog(#"Got to the 1st call for idAttribute... %#", idAttribute);
}
else { NSLog(#"There is no value for title..."); }
}
else { NSLog(#"Root element must be null..."); }
}
It finds the root element and gets to the call for valueOfAttribute:#"title" but the value is always (null).
So my question: do I have to do something to convert the NSData back to man readable (I was under the impression TBXML gave that option to work with the NSData and did the calculation). If not, what is the call to create (and then use) an NSString in UTF8 from 'myData'?
what is the call to create (and then use) an NSString in UTF8 from 'myData'?
use initWithData:encoding:
NSString *str = [[NSString alloc] initWithData:myData encoding:NSUTF8StringEncoding];
or stringWithUTF8String: if you know myData is null-terminated UTF8 string
NSString *str = [NSString stringWithUTF8String:[myData bytes]];
Do not ignore error.
NSError *error = nil;
TBXML *sourceXML = [[TBXML alloc] initWithXMLData:myData error:&error];
if (error) {
// handle it, at least log it
}
Related
Unable to parse this json data to object. Same code i tried with other URL, working correct. Please Suggest where i am doing wrong?
-(void)callAPI{
NSData *data=[NSData dataWithContentsOfURL:[NSURL URLWithString:#"https:s.json"]];
NSError *error=nil;
id response=[NSJSONSerialization JSONObjectWithData:data options:
NSJSONReadingMutableContainers | NSJSONReadingMutableLeaves error:&error];
if (error) {
NSLog(#"%#",[error localizedDescription]);
} else {
NSLog(#"%#",response);}}
Output The data couldn’t be read because it isn’t in the correct format.
I got the very perfect solution for your question which works fine now.Please check the below answer
- (void)callAPI
{
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
[request setHTTPMethod:#"GET"];
[request setURL:[NSURL URLWithString:#"https://dl.dropboxusercontent.com/s/2iodh4vg0eortkl/facts.json"]];
[[[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:
^(NSData * data,
NSURLResponse * response,
NSError * error) {
NSString *jsonString = [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding];
NSLog(#"jsonString is: %#", jsonString);
NSData *dataCon = [jsonString dataUsingEncoding:NSUTF8StringEncoding];
id jsonVal = [NSJSONSerialization JSONObjectWithData:dataCon options:0 error:nil];
if([jsonVal isKindOfClass:[NSDictionary class]]) {
NSLog(#"The response starts with NSDictionary");
NSArray *arrJsonVal = [jsonVal objectForKey:#"rows"];
NSMutableArray *arrTitle = [[NSMutableArray alloc]init];
NSMutableArray *arrDesc = [[NSMutableArray alloc]init];
NSMutableArray *arrImage = [[NSMutableArray alloc]init];
for(NSDictionary *dict in arrJsonVal) {
NSString *strTitle = [dict objectForKey:#"title"];
NSString *strDesc = [dict objectForKey:#"description"];
NSString *strImage = [dict objectForKey:#"imageHref"];
[arrTitle addObject:strTitle];
[arrDesc addObject:strDesc];
[arrImage addObject:strImage];
}
NSLog(#"arrTitle is - %#",arrTitle);
NSLog(#"arrDesc is - %#",arrDesc);
NSLog(#"arrImage is - %#",arrImage);
}else {
NSLog(#"The response starts with NSArray");
}
}] resume];
}
The Printed results are
After that
Then Array results are
Finally the results are
I am writing an application to authorise itself into Spotify. I used the node app.js example to get things working and an now re-writing natively into Objective C. I have extracted the authorisation code via a callback function
NSMutableURLRequest * request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:#"https://accounts.spotify.com/api/token"]];
request.HTTPMethod = #"POST";
// put in the header fields
NSString *headerString = [NSString stringWithFormat:#"%#:%#",clientID,clientSecret];
NSData *nsdata = [headerString dataUsingEncoding:NSUTF8StringEncoding];
NSString *base64Encoded = [nsdata base64EncodedStringWithOptions:0];
base64Encoded = [ NSString stringWithFormat:#"Basic %#", base64Encoded];
[request setValue:base64Encoded forHTTPHeaderField:#"Authorization"];
NSLog(#"request.header %#", request.allHTTPHeaderFields.description);
// put in the body form
NSString * stringData = [NSString stringWithFormat:#"grant_type:%#, code:%#, redirect_uri:\"%#\"", #"authorization_code",authorisationCode,redirectUri];
NSData * requestBodyData = [stringData dataUsingEncoding:NSUTF8StringEncoding];
request.HTTPBody = requestBodyData;
NSLog(#"request.body %#", [[NSString alloc] initWithData:request.HTTPBody encoding:NSUTF8StringEncoding]);
I then post this request and get
{"error":"server_error","error_description":"Unexpected status: 415"}
returned.
I have found a variety of questions on this topic revolving around the Content-Type needing to be application/x-www-form-urlencoded but this was no direct cure.
Anyone got any suggestions for me?
I found the answer here NSURLRequest : Post data and read the posted page
It appears that the raw data within the HTTPBody needs to be formatted differently - no JSON at all. The above link has a useful function which I updated slightly
-(NSData*)encodeDictionary:(NSDictionary*)dictionary {
NSMutableArray *parts = [[NSMutableArray alloc] init];
for (NSString *key in dictionary) {
NSString *encodedValue = [[dictionary objectForKey:key] stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLPasswordAllowedCharacterSet]];
NSString *encodedKey = [key stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLPasswordAllowedCharacterSet]];
NSString *part = [NSString stringWithFormat: #"%#=%#", encodedKey, encodedValue];
[parts addObject:part];
}
NSString *encodedDictionary = [parts componentsJoinedByString:#"&"];
return [encodedDictionary dataUsingEncoding:NSUTF8StringEncoding];
}
and ..
[request setValue:#"application/x-www-form-urlencoded" forHTTPHeaderField:#"Content-Type"];
//NSLog(#"request.header %#", request.allHTTPHeaderFields.description);
// put in the body form using the new function
NSDictionary * parameters = [[NSDictionary alloc] initWithObjectsAndKeys:#"authorization_code",#"grant_type",authorisationCode,#"code",redirectUri,#"redirect_uri", nil ];
NSData * requestBodyData = [self encodeDictionary:parameters];
request.HTTPBody = requestBodyData;
So I understand how to split the array that holds the JSON info, but what I am stuck on is trying to get it to display everything past only the first whitespace. For instance, if you look at the JSON site (http://iam.colum.edu/portfolio/api/course?json=True) each course has a course number at beginning. I want to split each array object only displaying the course name. For instance, if you look at the site, the first object is "Computer Architecture" second is "Digital Image and Design"... etc. I don't need to know how to split the string, I can already do that, but how do I split it so it takes away "xx-xxx " (x being the course number)? The code I have currently splits at each whitespace, but that's not going to work for obvious reasons.
JSONViewController
dispatch_async(progressQueue, ^{
jstring = [JSONHelper JSONgetString:#"http://iam.colum.edu/portfolio/api/course?json=True"];
dispatch_async(dispatch_get_main_queue(), ^{
//main thread code
//textView.text = jstring;
jarray = [jstring componentsSeparatedByString:#" "];
textView.text = [jarray objectAtIndex:1];
NSString * fullString = [NSString string];
for(int i = 0; i < jarray.count; i++)
{
fullString = [fullString stringByAppendingString:[jarray objectAtIndex:i]];
}
textView.text = fullString;
NSError *error = nil;
NSArray * resultArray = [NSJSONSerialization JSONObjectWithData: [jstring dataUsingEncoding:NSUTF8StringEncoding] options:NSJSONReadingMutableContainers error: &error];
if ( !resultArray ) {
NSLog(#"Error parsing JSON: %#", error);
} else {
for(NSString * course in resultArray) {
NSLog(#"Course: %#", course);
}
}
JSONHelper.h
#interface JSONHelper : NSObject
+ (NSDictionary *)JSONget:(NSString *)query;
+ (NSString *)JSONgetString:(NSString *)query;
+ (NSString *)JSONpostString:(NSString *)query;
+(NSString *)JSONpostString:(NSString *)query
withData:(NSString *)jsonData;
#end
JSONHelper.m
#implementation JSONHelper
//returns a dictionar from a get request
+ (NSDictionary *)JSONget:(NSString *)query
{
NSData *jsonData = [[NSString stringWithContentsOfURL:[NSURL URLWithString:query] encoding:NSUTF8StringEncoding error:nil] dataUsingEncoding:NSUTF8StringEncoding];
NSError *error = nil;
NSDictionary *results = jsonData ? [NSJSONSerialization JSONObjectWithData:jsonData options:0 error:&error] : nil;
if (error) NSLog(#"[%# %#] JSON error: %#", NSStringFromClass([self class]), NSStringFromSelector(_cmd), error.localizedDescription);
return results;
}
//returns JSON string from get request
+(NSString *)JSONgetString:(NSString *)query
{
NSString* searchURL = [NSString stringWithFormat:query];
NSError* error = nil; //error for NSUSRLConnection
NSURLResponse* response = nil;
NSMutableURLRequest* request = [[NSMutableURLRequest alloc] init];
NSURL* URL = [NSURL URLWithString:searchURL];
[request setURL:URL];
[request setCachePolicy:NSURLRequestReloadIgnoringLocalCacheData];
[request setTimeoutInterval:30];
NSData* data = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
if (error)
{
NSLog(#"Error performing request %#", searchURL);
return 0;
}
NSString *jsonString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog(#"jsonString:%#", jsonString);
return jsonString;
}
+(NSString *)JSONpostString:(NSString *)query{
NSString* searchURL = [NSString stringWithFormat:query];
NSError* error = nil;
NSURLResponse* response = nil;
NSMutableURLRequest* request = [[NSMutableURLRequest alloc] init];
NSURL* URL = [NSURL URLWithString:searchURL];
[request addValue: #"application/json" forHTTPHeaderField:#"Accept"];
[request addValue: #"application/json" forHTTPHeaderField:#"Content-Type"];
[request setHTTPMethod:#"POST"];
[request setURL:URL];
[request setTimeoutInterval:15];
NSData* data = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
if (error)
{
NSLog(#"Error performing request %#", searchURL);
return 0;
}
NSString *jsonString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog(#"jsonString:%#", jsonString);
return jsonString;
}
+(NSString *)JSONpostString:(NSString *)query
withData:(NSString *)jsonData
{
NSString* searchURL = [NSString stringWithFormat:query];
NSError* error = nil;
NSURLResponse* response = nil;
NSMutableURLRequest* request = [[NSMutableURLRequest alloc] init];
NSURL* URL = [NSURL URLWithString:searchURL];
[request addValue: #"application/json" forHTTPHeaderField:#"Accept"];
[request addValue: #"application/json" forHTTPHeaderField:#"Content-Type"];
[request setHTTPMethod:#"POST"];
[request setURL:URL];
[request setTimeoutInterval:30];
NSData* requestData = [jsonData dataUsingEncoding:NSUTF8StringEncoding];
[request addValue:[NSString stringWithFormat:#"%d", [requestData length]] forHTTPHeaderField:#"Content-Length"];
[request setHTTPBody:requestData];
NSData* data = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
if (error)
{
NSLog(#"Error performing request %#", searchURL);
return 0;
}
NSString *jsonString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog(#"jsonString:%#", jsonString);
return jsonString;
}
#end
NSDictionary *dictionary = [JSONHelper JSONget:#"http://iam.colum.edu/portfolio/api/course?json=True"];
for (id course in dictionary) {
NSLog(#"%#", [course substringFromIndex:8]);
}
As you can seen all those course number has the same pattern (so I assume that won't change) and it's xx-xxxx (7 character + whitespace after this). In that cas you can easily use substring fromthe index 8 (counting from 0).
Bu if you are still eager on how to do this in case when those course numbers may have various lengths yo can try using this solution:
NSDictionary *dictionary = [JSONHelper JSONget:#"http://iam.colum.edu/portfolio/api/course?json=True"];
for (id course in dictionary) {
NSArray *courseArray = [course componentsSeparatedByString:#" "];
NSMutableString *courseName = [NSMutableString string];
for (int i = 1; i < [courseArray count] ; i++) {
[courseName appendFormat:#"%# ", courseArray[i]];
}
// Deleting last character which is whitespace
[courseName substringToIndex:courseName.length -1];
NSLog(#"%#", courseName);
[courseName setString:#""];
}
It may not be the most efficent way to handle your problem but it just works!
i can't figure out one memory leak. I will add screen shot with code and marked line where this happens.
Maybe some could help me and take a look.
Thanks.
- (AVAudioPlayer*)getSpeachSoundObject{
NSString *objectIDString = [NSString stringWithFormat:#"%i", jmObject.objectID];
NSString * __weak textPlaySource = [DataController getMediaUrlStringForObjectID:objectIDString parentType:PARENT_TYPE_ITEM_AUDIO];
NSError * error = nil ;
if (textPlaySource) {
//NSURL *soundURL = [[NSURL alloc] initFileURLWithPath:textPlaySource];//[NSURL fileURLWithPath:textPlaySource];
NSData * data = [NSData dataWithContentsOfFile:textPlaySource options:NSDataReadingMapped error:&error ] ;
textPlaySource = nil;
NSError *error;
//speechSound = [[AVAudioPlayer alloc] initWithContentsOfURL:soundURL error:&error];
AVAudioPlayer *lspeechSound = data ? [[AVAudioPlayer alloc] initWithData:data error:&error ] : nil ;
data = nil;
if (error) {
WLog([NSString stringWithFormat:#"Error creating sound file:%#", error]);
}
return lspeechSound;
//soundURL = nil;
}
return nil;
}
I'm making URL Request to an API but I dont know how to render the JSON, It generates an array of multiple users like this [{"user": "value"}, {"user":"value"}] and I was trying to use a TableView so I need an NSDictionary but i think is better to render a JSON like {users: [{"user": "value"}, {"user":"value"}]}. I have this code to make the request
#import "JSONKit.h"
NSError *error = nil;
NSURLResponse *response = nil;
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL: [NSURL URLWithString: #"http://localhost:3000/getusers"]];
[request setHTTPMethod:#"GET"];
NSData *jsonData = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
users = [[jsonData objectFromJSONData] objectForKey:#"users"];
usersKeys = [users allKeys];
but I'm getting this error
2012-09-16 18:51:11.360 tableview[2979:c07] -[JKArray allKeys]: unrecognized selector sent to instance 0x6d30180
2012-09-16 18:51:11.362 tableview[2979:c07] * Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[JKArray allKeys]: unrecognized selector sent to instance 0x6d30180'
I dont really know how to accomplish this so any help is useful, thanks
You are getting that error because whatever got parsed out of "jsonData" isn't necessarily what you expected (i.e. a dictionary).
Perhaps you need some error checking in that code of yours.
For example:
NSData *jsonData = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
if(jsonData)
{
id objectReturnedFromJSON = [jsonData objectFromJSONData];
if(objectReturnedFromJSON)
{
if([objectReturnedFromJSON isKindOfClass:[NSDictonary class]])
{
NSDictionary * dictionaryFromJSON = (NSDictionary *)objectReturnedFromJSON;
// assuming you declared "users" & "usersKeys" in your interface,
// or somewhere else in this method
users = [dictionaryFromJSON objectForKey:#"users"];
if(users)
{
usersKeys = [users allKeys];
} else {
NSLog( #"no users in the json data");
}
} else {
NSLog( #"no dictionary from the data returned by the server... check the data to see if it's valid JSON");
}
} else {
NSLog( #"nothing valid returned from the server...");
}
} else {
NSLog( #"no data back from the server");
}
I was thinking on something like this
NSError *error = nil;
NSURLResponse *response = nil;
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL: [NSURL URLWithString: #"http://localhost:3000/getusers"]];
[request setHTTPMethod:#"GET"];
NSData *jsonData = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
JSONDecoder *decoder = [[JSONDecoder alloc]
initWithParseOptions:JKParseOptionNone];
NSArray *json = [decoder objectWithData:jsonData];
NSMutableArray *objects = [[NSMutableArray alloc] init];
NSMutableArray *keys = [[NSMutableArray alloc] init];
for (NSDictionary *user in json) {
[objects addObject:[user objectForKey:#"user" ]];
[keys addObject:[user objectForKey:#"value" ]];
}
users = [[NSDictionary alloc] initWithObjects:objects forKeys:keys];
NSLog(#"users: %#", users);
usersKeys = [users allKeys];
But it doesnt look efficient for many items or im wrong?