filling UITableView with JSON data won't work - ios

I'm having this problem. I'm trying to build an UITableView with data from a JSON Dictionary made with NSJSONSerialization. I have no idea where to start. i've been trying for 3 days but silo have achieved nothing. This is the code i've came up with:
#define kBgQueue dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)
#define kJsonURL [NSURL URLWithString: #"http://rs-hosting.nl/panel/serverstatus_json.php"]
#import "ViewController.h"
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
dispatch_async(kBgQueue, ^{
NSData* data = [NSData dataWithContentsOfURL:kJsonURL];
[self performSelectorOnMainThread:#selector(fetchedData:) withObject:data waitUntilDone:YES];
});
}
- (void)fetchedData:(NSData *)responseData {
NSError* error;
NSDictionary* json = [NSJSONSerialization JSONObjectWithData:responseData options:kNilOptions error:&error];
NSDictionary *clients = [json objectForKey:#"announcements"];
NSArray *announcements = [clients objectForKey:#"announcement"];
NSDictionary* announcement = [announcements objectAtIndex:1];
}
- (void)viewDidUnload {
[super viewDidUnload];
}
#end
I'm able to display content in a label on a single view in a label but i have no clue how to het all the data in the json to a table. Can someone please healp me out?
SDK: 5.1
OSX: 10.7.3
XCODE: 4.3.1
Tnx in advance

You need to store your data somewhere (keeping that NSDictionary with the whole json file is fine for a start) and then add a UITableView, set it up to point its data source to your class and then implement the UITableViewDataSource methods as outlined.
The UITableView will then request data from these methods as it fills in the table. The only two required methods are tableView:numberOfRowsInSection: and tableView:cellForRowAtIndexPath: so start with those two and get the data displaying on the table before doing any other customization.

after getting data in NSDictionary, save it in NSArray filled with NSString objects that u want to show and then call the function [Tableview reloadData]; in you ViewDidLoad function and ur good to go.

Related

How to push a target to a point page according to the request result from database?? (ios)

It's bit of complicated but I will explain as possible as I can. I have 10 pages in a app with the unique variable id (1~10), each page has a uialertview with 2 buttons, yes/no. when I press yes, the app will send a data to a table in a database, and then retrieve a data from another table. The return data will contain a number ("3" for example). what I need to do is to push the button to the corresponding page after received a number from database. (ie: if I press yes, the app receive 3 from database, the button will push to id3 page)
what I have done:
I have settle done a database. The app is able to send a data to the database, and is also able to receive a data from database, however, I do not know how to push the button to the corresponding page after received a data.
I have a class in the yes button (.h)
#import <Foundation/Foundation.h>
#import "RecommendationData.h"
#interface DataConnection : NSObject <UIAlertViewDelegate>{
NSMutableArray *json;
}
-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex;
#end
and(.m)
#import "DataConnection.h"
#implementation DataConnection
-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{
if (buttonIndex ==1) {
[self sendData];
[self receiveRecommendData];
}
}
-(void) sendData {
//send data//
RecommendationData *obj = [RecommendationData getInstance];
// create string contains url address for php file
NSString *strURL = [NSString stringWithFormat:#"http://phdprototype.tk/phpFile.php?maxValue=%#&collectionId=%#&level=%#&room=%#", obj.maxValue, obj.collectionId, obj.level, obj.room];
// to execute php code
NSData *dataURL = [NSData dataWithContentsOfURL:[NSURL URLWithString:strURL]];
// to receive the returend value
NSString *strResult = [[NSString alloc] initWithData:dataURL encoding:NSUTF8StringEncoding];
NSLog(#"%#", strResult);
}
-(void) receiveRecommendData {
//receive data//
NSURL *getResultUrl = [NSURL URLWithString:#"http://phdprototype.tk/getResultData.php"];
NSData *data = [NSData dataWithContentsOfURL:getResultUrl];
[self getData:data];
}
-(void) getData:(NSData *) data{
NSError *error;
json = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error];
}
#end
Now, the received json data from database is
[{"max(id)":"3","recommendData":"8","room":"4F","level":"2"}]
in this case, the return ID is 8, so I would like to push the button to page8. In each page I have some codes in .m to set the unique id
RecommendationData *obj = [RecommendationData getInstance];
obj.collectionId=#"8";
can anyone provide some codes for me to complete this task?? Thanks

how to table Reload ios when recieving response Data

Hi My problem is that i am getting a response from a web service and when i parse it and add to table and reload the table view it is not refreshing . Although if i call the [table reload] in keyboard is shown it gets updated there. Could someone tell me if im missing anything
This is what i am trying to do
- (void) longPoll {
//create an autorelease pool for the thread
#autoreleasepool {
NSLog(#"polling");
VSAppDelegate *var = (VSAppDelegate*)[[UIApplication sharedApplication] delegate];
//compose the request
NSError* error = nil;
NSHTTPURLResponse* response = nil;
//send the request (will block until a response comes back)
NSData* responseData = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
NSLog(#"polling response is %d",response.statusCode);
//pass the response on to the handler (can also check for errors here, if you want)
[self performSelectorOnMainThread:#selector(dataReceived:) withObject:responseData waitUntilDone:YES];
}
[self performSelectorInBackground:#selector(longPoll) withObject: nil];
}
- (void) startPoll {
[self performSelectorInBackground:#selector(longPoll) withObject: nil];
}
- (void) dataReceived: (NSData*) theData
{
//process the response here
NSError *error = nil;
NSLog(#"polling data is %#",[[NSString alloc] initWithData:theData encoding:NSUTF8StringEncoding]);
NSLog(#"polling data is %#",[[theData base64EncodedString]base64DecodedString]);
NSDictionary *notifDic= [NSJSONSerialization JSONObjectWithData:theData options:kNilOptions error:&error];
//VSViewControllerSplit *split = [[VSViewControllerSplit alloc]init];
[self RecieveFunction:notifDic];
}
try it
dispatch_async(dispatch_get_main_queue(), ^{
[tablrView reloaddata];
});
The dataReceived method doesn't appear to be calling reloadData. I'll assume that RecieveFunction method does, though, but you should confirm that. It's hard to say without seeing RecieveFunction.
The more fundamental issue would appear to be that dataReceived method is creating a new instance of VSViewControllerSplit, calling its RecieveFunction method, and then letting this new VSViewControllerSplit instance fall out of scope (and if using ARC, get deallocated unless you pushed to it, presented it, etc.). You presumably don't want to create a new VSViewControllerSplit every time longPoll calls dataReceived, but rather just reference the existing instance.

Getting Flickr RecentActivity images

I want to retrieve Recent Activity images from flickr application, please any one suggest me how to retrieve that. thanks in advance.
This is not the best way of doing this but I will provide you a way to retrieve recent pictures on flickr. Standford iTunesU had a few lectures that related to this. I am getting almost all of my information from them. Here is a link to the course material:
http://www.stanford.edu/class/cs193p/cgi-bin/drupal/
For the basic, non multithreaded version look under lecture 10 and download Shutterbug Universal. You will also need a flickr API key which you can currently get here:
http://www.flickr.com/services/api/misc.api_keys.html
I will attempt to outline for you though how to go about completing your request, especially since either of those links may not be around for long.
You will want to create a class FlickrFetcher or something, then have a public class method
+ (NSArray *)latestGeoreferencedPhotos;
Implementation
+ (NSArray *)latestGeoreferencedPhotos
{
NSString *request = [NSString stringWithFormat:#"http://api.flickr.com/services/rest/?method=flickr.photos.search&per_page=500&license=1,2,4,7&has_geo=1&extras=original_format,tags,description,geo,date_upload,owner_name,place_url"];
return [[self executeFlickrFetch:request] valueForKeyPath:#"photos.photo"];
}
Where executeFlickrFetch is implemented:
+ (NSDictionary *)executeFlickrFetch:(NSString *)query
{
query = [NSString stringWithFormat:#"%#&format=json&nojsoncallback=1&api_key=%#", query, FlickrAPIKey];
query = [query stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSData *jsonData = [[NSString stringWithContentsOfURL:[NSURL URLWithString:query] encoding:NSUTF8StringEncoding error:nil] dataUsingEncoding:NSUTF8StringEncoding];
NSError *error = nil;
NSDictionary *results = jsonData ? [NSJSONSerialization JSONObjectWithData:jsonData options:NSJSONReadingMutableContainers|NSJSONReadingMutableLeaves error:&error] : nil;
if (error) NSLog(#"[%# %#] JSON error: %#", NSStringFromClass([self class]), NSStringFromSelector(_cmd), error.localizedDescription);
return results;
}
You will need to get your API key and either define it (#define FlickrAPIKey #"myAPIkey") or just directly insert it here.
In the Standford course they call latestGeoreferencedPhotos from a TVC subclass and set an array of photos in viewDidLoad:
// photos is a defined property
self.photos = [FlickrFetcher latestGeoreferencedPhotos];
Then in the setter for photos they reload a tableView that presents the images:
- (void)setPhotos:(NSArray *)photos
{
_photos = photos;
[self.tableView reloadData];
}
photos is now an array of dictionaries where so you can access specific image data by doing things like:
return [self.photos[row][#"title"] description]; // description because could be NSNull
I did find a github resource that may be valuable:
https://github.com/lukhnos/objectiveflickr.
I did not look into it much but it is probably worth checking into!
Your question did not provide much detail so I hope that this answer is sufficient for your needs.

Scope and threading in iOS

I am kind of new to web service calls and threading in iOS. I have a ViewController in my app that contains a tableview control. I am populating the table with data obtained via a JSON web service. The JSON web service is called on its own thread, during which I am populating an NSArray and NSDictionary.
My array and dictionary seem like they are going out of scope since my NSLog statement is returning zero for the array count even though while in fetchedData the array is fully populated.
Can someone offer an explanation as to why my array and dictionary objects are empty outside of the thread?
- (void)viewDidLoad
{
[super viewDidLoad];
NSString *serviceEndpoint = [NSString stringWithFormat:
#"http://10.0.1.12:8888/platform/services/_login.php?un=%#&pw=%#&ref=%#",
[self incomingUsername], [self incomingPassword], #"cons"];
NSURL *url = [NSURL URLWithString:serviceEndpoint];
dispatch_async(kBgAdsQueue, ^{
NSData *data = [NSData dataWithContentsOfURL:url];
[self performSelectorOnMainThread:#selector(fetchedData:) withObject:data waitUntilDone:YES];
});
NSLog(#"ARRAY COUNT: %d\n", [jsonArray count]);
}
-(void)fetchedData:(NSData*)responseData{
NSError *error;
jsonDict = [NSJSONSerialization JSONObjectWithData:responseData options:kNilOptions error:&error];
jsonArray = [[jsonDict allKeys]sortedArrayUsingSelector:#selector(compare:)];
for(NSString *s in jsonArray){
NSLog(#"%# = %#\n", s, [jsonDict objectForKey:s]);
}
}
When you use dispatch_async, that bit of code doesn't block. This means your array count log statement triggers before fetchedData is called, so your dictionary and array are still empty. Look at the order of your log statements - you should see array count before your logging of the dictionary.
// Executes on another thread. ViewDidLoad will continue to run.
dispatch_async(kBgAdsQueue, ^{
NSData *data = [NSData dataWithContentsOfURL:url];
[self performSelectorOnMainThread:#selector(fetchedData:) withObject:data waitUntilDone:YES];
});
// Executes before the other thread has finished fetching the data. Objects are empty.
NSLog(#"ARRAY COUNT: %d\n", [jsonArray count]);
You'll need to finish populating your TableView after the data returns (ie in FetchData:).
The log statement within viewDidLoad SHOULD report that the array is empty as it has not been populated at that time. Calling dispatch_async causes that block of code to be run asynchronously and allows the viewDidLoad function to finish before the block does. That's why you have nothing in your array at the end of viewDidLoad.
You are trying to print count of jsonArray elements before it was populated. Here is what happens:
You prepare url
You create new thread to fetch some date. Execution of this thread may take some time (depending on connection speed and amount of data).
You are accessing jsonArray while thread is executing and fetchedData: was not called
Also, suggestion:
Don't use dataWithContentsOfURL: methods. Better take a look at some networking frameworks like AFNetworking.

warning: Attempting to create USE_BLOCK_IN_FRAME

I get this warning in Xcode
warning: Attempting to create USE_BLOCK_IN_FRAME variable with block
that isn't in the frame.
Xcode redirect me to my NSStream
_naturStream = [[NSInputStream alloc] initWithData:natur];
It is random when it does this error, and my application crashes when it is triggered. Anyone tried similar problem ?
thanks
EDIT
in the appDelegate.h
#property (nonatomic, strong) NSInputStream *naturStream;
In the appDelegate.m:
NSData *natur = [NSData dataWithContentsOfURL:[NSURL URLWithString:_locString]];
_naturStream = [[NSInputStream alloc] initWithData:natur];
[_naturStream open];
if (_naturStream) {
NSError *parseError = nil;
id jsonObject = [NSJSONSerialization JSONObjectWithStream:_naturStream options:NSJSONReadingAllowFragments error:&parseError];
if ([jsonObject respondsToSelector:#selector(objectForKey:)]) {
for (NSDictionary *natur in [jsonObject objectForKey:#"results"]) {
_poi = [[POI alloc]init];
[_poi setTitle:[natur objectForKey:#"title"]];
[_poi setLat:[[natur objectForKey:#"lat"]floatValue]];
[_poi setLon:[[natur objectForKey:#"lng"]floatValue]];
[_poi setDistance:[natur objectForKey:#"distance"]];
[_poi setWebUrl:[natur objectForKey:#"webpage"]];
[_naturArray addObject:_poi];
}
}
}
else {
NSLog(#"Failed to open stream.");
}
[_naturStream close];
}
I realized that i forgot [_naturStream close] i don't know if it has solved the problem or not ?
EDIT
Another thing,.... I use a Thread for fetching the JSON data:
dispatch_queue_t jsonParsingQueue = dispatch_queue_create("jsonParsingQueue", NULL);
// execute a task on that queue asynchronously
dispatch_async(jsonParsingQueue, ^{
[self parseJSON];
dispatch_async(dispatch_get_main_queue(), ^{
[_kortvisning updateAnno];
[visListe updateList];
});
});
// release the dispatch queue
dispatch_release(jsonParsingQueue);
Sounds like you're using ARC - if _naturStream is an instance variable for an objective C class, you might need to pull it out and add a __block reference so that ARC knows the scope correctly - but I'm guessing because I don't see how the block is used with the NSInputStream (if you post that part we might know). A good bit is here: http://nachbaur.com/blog/using-gcd-and-blocks-effectively
-- edit --
Ok, now that you posted the rest, I bet it has to do with the _kortvisning and visListe variables. I think you want to pull those out right after you create your queue something like
__block KortVisning *localKortVisning = _kortvisning;
__block NSMutableArray *localVisListe = visListe;
Then access those directly from your final completion handler you're sending back to the main queue.

Resources