I currentley have a jSON file which is created a by a script which can be seen here: http://ddelay.co.uk/bus/output.json
I currently have managed to setup the following to grab the JSON which works, i just cannot figure how to grab the data to assign it :/
-(void)makeStopRequests{
NSURL *url = [NSURL URLWithString:#"http://ddelay.co.uk/bus/output.json"];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
//AFNetworking Asynchronous Task
AFJSONRequestOperation *operation = [AFJSONRequestOperation
JSONRequestOperationWithRequest:request
success:^(NSURLRequest *request, NSHTTPURLResponse *response, id responseObject)
{
NSLog(#"JSON RESULT %#", responseObject);
self.stopArray = [responseObject objectForKey:#"stop_name"];
[self.tableView reloadData];
}
failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id responseObject)
{
NSLog(#"Request Failed: %#, %#", error, error.userInfo);
}];
[operation start];
}
I hope somebody can guide me through how I would select the data,
Thank you.
Damien
I would recommend just using something as simple as NSJSONSerialization, which is built into iOS after iOS 5 (may have been earlier, but not too sure).
Just get the data from the request and then parse that into a dictionary with the following code
NSDictionary *dict= [NSJSONSerialization JSONObjectWithData:webData options:NSJSONReadingMutableLeaves error:nil];
get the data using the standard built in networking structure as well
NSURLRequest *someRequest = [[NSURLRequest alloc] initWithURL:someURL cachePolicy:NSURLRequestReloadRevalidatingCacheData timeoutInterval:10.0];
NSURLConnection *someConnection= [[NSURLConnection alloc] initWithRequest:someRequest delegate:self];
And then do whatever appropriate delegation and data processing. Read the documentation to get more details
You are using AFNetworking and it provides you the response object. That is already being cast to Objective c object.
You can simply assign it to NSArray or NSDictionary like this
NSArray *array = (NSArray*)responseObject;//if your json returns an array
NSDictionay *dict (NSDictionary*)responseObject;//if json returns dictionary.
This url returns JSON in this format;
[ {
"service":"22",
"provider":"First in Yorkshire",
"dest":"Nether Edge to Woodhouse",
"dest URL":"/web/public_service_stops.asp?service=22&operatorid=31&systemid=30&goingto=Woodhouse"
},
{
"service":"22",
"provider":"First in Yorkshire",
"dest":"Barnsley to Rotherham",
"dest URL":"/web/public_service_stops.asp?service=22&operatorid=31&systemid=30&goingto=Rotherham"
}
]
Which actually is an array of dictionaries so to access data you have to loop like this.
NSArray *jsonResponse = (NSArray*)responseObject;
for (NSDictionary *dic in jsonResponse){
NSString *service = [dic valueForKey:#"service"];
NSString *provider = [dic valueForKey:#"provider"];
//Same for others
//It will better you create calss with these properties and then add that object to an Array, and on reloading data in table get that object from array in cellForRowAtIndexPath and use requried property to populate your data.
//Or if you just want to use stop name add stop name to array and use it.
NSString *stopName =[dic valueForKey:#"stop_name"];
//[dataArray addObject:stopName]; in case you want to use only stop name
}
Here's minimal code:
self.stopArray = responseObject;
for (NSDictionary *stopDict in self.stopArray) {
NSString *service = [stopDict objectForKey:#"service"];
NSString *provider = [stopDict objectForKey:#"provider"];
NSString *dest = [stopDict objectForKey:#"dest"];
NSString *destURL = [stopDict objectForKey:#"dest URL"];
// do something with this data
}
For anything more complex than this, you'll probably want to make your own data class, so you don't have to parse through dictionaries and arrays in your table view delegate methods.
Related
I have have some trouble in understanding what is needed to fetch a JSON file with mantle.h from a URL.
Can someone give me an example of how it works?
For example:
-I have a URL www.example.com with a JSONFile as follows:
{
"name": "michael"
}
How could I fetch it?
I use this process for fetching JSON:
NSURL *s = url;//Put your desird url here
NSURLRequest *requestURL = [NSURLRequest requestWithURL:s cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:20.00];
NSHTTPURLResponse *response;
NSError *error = [[NSError alloc]init];
NSData *apiData = [NSURLConnection sendSynchronousRequest:requestURL returningResponse:&response error:&error];
dictionaryData = [NSJSONSerialization JSONObjectWithData:apiData options:kNilOptions error:&error];
Now the dictionaryData contains your JSON. You can fetch it by:
NSString *name = [dictionaryData valueForKey:#"name"];
And make sure you are making async request. For this put the code within this block:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
//Put the code here
});
Hope this helps.. :)
Call it with following method
[super getRequestDataWithURL:urlString
andRequestName:sometext];
You will get response in the following method if successful
- (void)successWithRequest:(AFHTTPRequestOperation *)operation withRespose:(id)responseObject withRequestName:(NSString *)requestName {
NSString *response = operation.responseString;
id jsonObject = [response objectFromJSONString];
if(![super checkforServerRequestFailureErrorMessage:jsonObject]) {
[self.leaderboardProxyDelegate leaderboardListSuccessful:jsonObject];
}
}
You will get dictionary in jsonObject
I am trying to store data from server to NSMutable array to display them as news feeds in table view like shown in this image. Basically like twitter news feeds. What I wanna do is get the data from the server in the NSMutable array and use that array to display in my table view. I don't know if this is the right way to do it. I tried adding statically and it works but I really don't know how to do it dynamically since I'm a newbie to Objective C. Sorry if this question seems really stupid. Thanks in advance!
Parse data using JSON:
dispatch_queue_t jsonParsingQueue = dispatch_queue_create("jsonParsingQueue", NULL);
// execute a task on that queue asynchronously
dispatch_async(jsonParsingQueue, ^{
NSString *urlStr = #"YourURL";
NSURL *url = [NSURL URLWithString:[urlStr stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc]initWithURL: url];
[request setHTTPMethod: #"GET"];
NSData *response = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];
NSString *responseStr = [[NSString alloc] initWithData:response encoding:NSUTF8StringEncoding];
NSData * jsonData = [responseStr dataUsingEncoding:NSUTF8StringEncoding];
NSMutableArray *tempResults = [NSMutableArray alloc];
NSError *jsonParsingError = nil;
NSDictionary *jsonObject = [NSJSONSerialization JSONObjectWithData:jsonData options:0 error:&jsonParsingError];
tempResults = jsonObject[#"posts"]; //Add the json key you would like to get
self.arrayToDisplay = [tempResults copy]; //copy them to your NSMutableArray
// some code on a main thread (delegates, notifications, UI updates...)
dispatch_async(dispatch_get_main_queue(), ^{
[self.myTableView reloadData];
});
});
I am making two separate requests to obtain JSON from external sources, I have so far implemented the display of the data from the first request into my table view. My problem is, I need to combine both sets of data into a single table view and sort the data by a common key, which in this case is created_time. I understand I can use some form of array, but how would I go about doing this?
The first:
NSURL *url = [NSURL URLWithString:myURL];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
AFJSONRequestOperation *operation = [AFJSONRequestOperation
JSONRequestOperationWithRequest:request
success:^(NSURLRequest *request, NSHTTPURLResponse *response, id json) {
self.results = [json valueForKeyPath:#"data"];
[self.tableView reloadData];
} failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON) {
}];
[operation start];
The second:
NSURL *url = [NSURL URLWithString:#"https://api.twitter.com/1.1/search/tweets.json"];
NSDictionary *parameters = #{#"count" : RESULTS_PERPAGE,
#"q" : encodedQuery};
SLRequest *slRequest = [SLRequest requestForServiceType:SLServiceTypeTwitter
requestMethod:SLRequestMethodGET
URL:url
parameters:parameters];
NSArray *accounts = [self.accountStore accountsWithAccountType:accountType];
slRequest.account = [accounts lastObject];
NSURLRequest *request = [slRequest preparedURLRequest];
dispatch_async(dispatch_get_main_queue(), ^{
self.connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
[UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
});
To combine the data from your external sources, you'll want to do the following for each response you get back.
Also, for the sake of the example, I'm assuming the objects you'll be dealing with are all dictionaries. If they aren't, you'll want to add some logic in the comparison block to get at the created_time value depending upon the type of object each one is.
NSArray *data = [json valueForKeyPath: #"data"]; // This is the data from your first example. You'll have to do the same for your second example.
NSMutableArray *allResults = [NSMutableArray arrayWithArray: self.results];
[allResults addObjectsFromArray: data];
[allResults sortUsingComparator: ^NSComparisonResult(id obj1, id obj2) {
NSDictionary *dict1 = obj1;
NSDictionary *dict2 = obj2;
return [[dict1 objectForKey: #"created_time"] compare: [dict2 objectForKey: #"created_time"]];
}];
[self setResults: allResults];
[self.tableView reloadData];
I am using AFJSONRequestOperation to request a remote API:
NSURLRequest *request = [NSURLRequest requestWithURL:url];
AFJSONRequestOperation *operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) {
//Remove the SVProgressHUD view
[SVProgressHUD dismiss];
//Check for the value returned from the server
NSData *jsonData = [JSON dataUsingEncoding:NSUTF8StringEncoding];//This line cause crash
NSArray *arr = [NSJSONSerialization JSONObjectWithData:jsonData
options:0
error:nil];
loginDic=[[NSDictionary alloc]init];
loginDic=[arr objectAtIndex:0];
NSLog(#"%#",loginDic);
} failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON) {
NSLog(#"Request Failed with Error: %#", [error.userInfo objectForKey:#"NSLocalizedDescription"]);
}];
[operation start];
[SVProgressHUD showWithStatus:#"Loading"];
However, the app crashes and I am getting this error:
[__NSCFDictionary dataUsingEncoding:]: unrecognized selector sent to instance
Here is an NSLog for the JSON object returned:
Result = (
{
operation = 5;
result = 1;
}
);
Am I missing something, because I think that I am not parsing correctly the JSON object. Please correct me.
It looks like AFJSONRequestOperation is deserializing JSON to a dictionary for you, and then you're trying to do it again. JSON is an NSDictionary but you're calling an NSString method.
Remove all of this code:
NSData *jsonData = [JSON dataUsingEncoding:NSUTF8StringEncoding];//This line cause crash
NSArray *arr = [NSJSONSerialization JSONObjectWithData:jsonData
options:0
error:nil];
loginDic=[[NSDictionary alloc]init];
loginDic=[arr objectAtIndex:0];
And replace it with:
loginDic = [[JSON objectForKey:#"Result"] lastObject];
(That'll work safely without checking array bounds, but assumes that there's only one element in the array.)
The object you get in the success block is already parsed by AFJSONRequestOperation.
In your case you get a NSDictionary object.
You can check the class of the object using the isKindofClass-method:
if ([JSON isKindOfClass:[NSDictionary class]]) {
NSDictionary* dict = (NSDictionary*)JSON;
...
}
I'm making several request from different sources, and because of this I want to add a property like: '"newsSource" = twitter' (JSON format) to the created NSArray resultsTwitter below. The reason is I want be able to handle each "newsitem" uniquely.
I'm new to blocks, but I think it might be an really easy way to do this "on the fly"?
If not possible within the block operation, any suggestion on how to do it after operation is done?
// Fetch data from Twitter (json complient)
NSURLRequest *request = [NSURLRequest requestWithURL:urlTwitter];
AFJSONRequestOperation *operation;
operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request
success:^(NSURLRequest *req, NSHTTPURLResponse *responce, id jsonObject) {
NSLog(#"Responce: %#",jsonObject);
self.resultsTwitter = [jsonObject objectForKey:#"results"];
[self.tableView reloadData];
}
failure:^(NSURLRequest *req, NSHTTPURLResponse *responce, NSError *error, id jsonObject) {
NSLog(#"Recieved an HTTP %d", responce.statusCode);
NSLog(#"The error was: %#",error);
}];
[operation start];
I may not have understood your question correctly, but as long as resultsTwitter is a NSMutableArray, you can add an object (in your case an NSDictionary with a single KVP) after it is initially populated.
Something like:
[resultsTwitter addObject:[NSDictionary dictionaryWithObjectsAndKeys:
#"twitter", #"newsSource",
nil]];
Example of instantiating a variable that can be accessed inside a block:
__block NSString *newssource = #"";
NSURLRequest *request = [NSURLRequest requestWithURL:urlTwitter];
AFJSONRequestOperation *operation;
operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request
success:^(NSURLRequest *req, NSHTTPURLResponse *responce, id jsonObject) {
NSLog(#"Responce: %#",jsonObject);
self.resultsTwitter = [jsonObject objectForKey:#"results"];
[self.tableView reloadData];
newssource = #"twitter";
}
failure:^(NSURLRequest *req, NSHTTPURLResponse *responce, NSError *error, id jsonObject) {
NSLog(#"Recieved an HTTP %d", responce.statusCode);
NSLog(#"The error was: %#",error);
}];
[operation start];
Create a Model class to encapsulate the behavior of all News Items.
This pattern is used in the AFNetworking example app, with each App.net post corresponding to a model object, which is initialized from JSON. I would strongly recommend against using a mutable dictionary rather than a model object as a means of representing items.