I am new to iOS. i have to parse following JSON and display it to UITableViewCell. individual array is appearing in cell when i parse and append country item only. but all arrays for ex. rank ,country , population , flag are not appearing in cell.
how to add all rank , country , population , flag in array and put all them in cell. i have taken all them into string and then into array. and whole array i appended to main array.
following is JSON -
http://www.androidbegin.com/tutorial/jsonparsetutorial.txt
code
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
NSDictionary *allDataDictionary = [NSJSONSerialization JSONObjectWithData:webdata options:0 error:nil];
NSArray *arrayWorldPopulation = [allDataDictionary objectForKey:#"worldpopulation"];
for (NSDictionary *diction in arrayWorldPopulation)
{
NSString *country = [diction objectForKey:#"country"];
NSString *population = [diction objectForKey:#"population"];
NSString *flag = [diction objectForKey:#"flag"];
NSArray *temparray = [[NSArray alloc] initWithObjects:rank,country,population,flag, nil];
[array addObject:temparray];
}
[maintableView reloadData];
}
At a minimum, you need to implement tableView:numberOfRowsInSection: and tableView:cellForRowAtIndexPath in your view controller. This tells the table how many rows to expect and what each row in the table looks like. The simple code below assumes you have an array of strings and are just displaying one string per cell and should get you started. Your specific situation sounds like it may require a custom cell design. This tutorial describes how to do this in a storyboard with a custom cell class.
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [array count]; //tell the UITableView how many are items are in the array
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath: (NSIndexPath *)indexPath
{
//stuff to make sure iOS is reusing cells rather than creating new ones
static NSString *MyIdentifier = #"MyReuseIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:MyIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:MyIdentifier];
}
NSString *itemFromArray = [array objectAtIndex:indexPath.row]; //get the item for that cell
cell.textLabel.text = itemFromArray; set the cell to display the text
return cell;
}
Related
I am trying to get my NSdictionary values into a UITableViewCell. Here is my dictionary format:
{
date = "3/4/14, 3:33:01 PM Pacific Standard Time";
weight = 244;
}
Here is the code I'm using to populate my uitableview (which is not working).
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *simpleTableIdentifier = #"WeightCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpleTableIdentifier];
}
NSArray* allKeys = [weights allKeys];
NSDictionary *obj = [allKeys objectAtIndex: indexPath.row];
cell.textLabel.text = [obj objectForKey: #"date"];
cell.detailTextLabel.text = [obj objectForKey:#"weight"];
return cell;
}
You should try initialising the array for the tableView outside of the tableView itself... something along the lines of
- (void)viewDidLoad
{
[super viewDidLoad];
_allKeys = [[NSMutableArray alloc] initWithArray:[weights allKeys]];
}
Once you have initialised that data you can access it throughout the process. Also to find out how many rows your tableview needs.
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [_allKeys count];
}
Then when you access the array into a dictionary it has retained the row count and can access it properly.
NSDictionary *obj = [_allKeys objectAtIndex: indexPath.row];
cell.textLabel.text = [obj objectForKey: #"date"];
cell.detailTextLabel.text = [obj objectForKey:#"weight"];
From what I can see the dictionary cant access the array at your indexPath.row because you haven't initialised the array anywhere before you use it in your tableView.
Hope that helps, T
Some of the other posters have good suggestions. However, this line:
NSDictionary *obj = [allKeys objectAtIndex: indexPath.row];
Is wrong. allKeys is an array of your dictionary keys, which are presumably strings.
So, you want code like this instead:
NSString *thisKey = allKeys[indexPath.row];
NSDictionary *obj = weights[thisKey];
Note that I am using the new Objective C literal syntax. The expression weights[thisKey] is equivalent to [weights objectForKey: thisKey]
I don't see the definition of the weights object. If you want to keep adding NSDictionary's to an array, you need to use an NSMutableArray, and you'll probably want to do that by setting it as a #property on your class. Let's say you added it like this:
#property (strong, nonatomic) NSMutableArray *weights;
Then in your tableView:cellForRowAtIndexPath: method you'll want to get the NSDictionary corresponding to that line by using self.weights[indexPath.row]. Also don't forget to instantiate weights before using it, otherwise it will return nil and no objects are going to be added to it.
P.S.: the user provided some context here and what he probably needs is Core Data.
I have a program that connects to a MAMP server and selects my database and displays the contents in the Xcode simulator. Right now I have 2 tabs and the data is the same for both. I want the tabs to seperate the type of data to display in each tab. (1 tab should display types of wine grape and the other displays wine countries)
I think that I have to make a class (subclass of NSObject) that pulls the data, then another view controller with a mutable array that holds the data needed for each tab but HOW do I do this? How do I create a MutableArray?
Here the code in my TableViewController.m, which connects to my database using JSON:
- (void)viewDidLoad
{
[super viewDidLoad];
NSURL *url = [NSURL URLWithString:#"http://[localhost]:8888/wine.php"]; // Modify this to match your url.
NSString *jsonreturn = [[NSString alloc] initWithContentsOfURL:url]; // Pulls the URL
NSLog(jsonreturn); // Look at the console and you can see what the restults are
NSData *jsonData = [jsonreturn dataUsingEncoding:NSUTF32BigEndianStringEncoding];
NSError *error = nil;
// In "real" code you should surround this with try and catch
NSDictionary * dict = [[CJSONDeserializer deserializer] deserializeAsDictionary:jsonData error:&error];
if (dict)
{
rows = [[dict objectForKey:#"wine"] retain];
}
NSLog(#"Array: %#",rows);
[jsonreturn release];
}
Then I created another method for the tableview:
pragma mark - Table view data source
(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [rows count];
}
// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] autorelease];
}
// Configure the cell.
NSDictionary *dict = [rows objectAtIndex: indexPath.row];
//cell.textLabel.text = [dict objectForKey:#"id"];
//cell.textLabel.text = [dict objectForKey:#"wineColor"];
//cell.textLabel.text = [dict objectForKey:#"wineGrape"];
cell.textLabel.text = [dict objectForKey:#"wineCountry"];
cell.detailTextLabel.text = [dict objectForKey:#"id"];
return cell;
}
with this, the same data (the wine countries) is displayed in both Grape & Country tabs. How can I create a Mutable Array that will grab what data should be displayed in each tab?
You need the second (Grape) view controller to implement the tableView datasource and delegate methods for its own tableview, but you don't need another array, you can use your JSON dictionary, but add the proper text to labels within your cells for grapes (in the cellForRowAtIndexPath UITableView datasource method). You would use the lines above that are currently commented out to populate your labels in cells of your "Grape" table view:
//cell.textLabel.text = [dict objectForKey:#"wineColor"];
//cell.textLabel.text = [dict objectForKey:#"wineGrape"];
You could add a custom UITableViewCell or use the subtitle style and set the subtitle to color.
I have a split view controller for iPad with a drill-down table on the left. I am able to populate my first table view and when I click on a cell this takes me to my second table view. I am able to see a count of records returned and the actual data I expect to see in the table view output in the command widow with the NSLog command. What I don't see is the actual data in the table view. Instead I see UITableViewCellAccessoryDisclosureIndicator for each row that is returned but no actual data.
I am using xib files and I have created this file for my products I want displayed in the drill-down. In my Product.xib file I have the File's Owner Outlets as productsTableView linked to products (my UITableView control) and view linked to View. Referencing Outlets for the View have dataSource linked to products, delegate linked to products and finally view linked to File's Owner.
Am I missing something here? Like I said I get all the data back it just isn't binding to the grid.
#interface ProductViewController : UIViewController <UITableViewDataSource, UITableViewDelegate> {
NSMutableArray *listOfItems;
NSMutableArray *dataArray;
IBOutlet UITableView *productsTableView;
}
#property(nonatomic, strong) IBOutlet UITableView *productsTableView;
#end
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
// Set up the cell...
NSString *cellValue = [listOfItems objectAtIndex:indexPath.row];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
cell.textLabel.text = cellValue;
return cell;
}
In the interest of being thorough I will post this as well to show where I am getting my data back and how I am doing this...
-(void) connectionDidFinishLoading:(NSURLConnection *)connection {
NSError *error = nil;
// Get the JSON data from the website
id result = [NSJSONSerialization JSONObjectWithData:receivedData options:kNilOptions error:&error];
if ([result isKindOfClass:[NSArray class]]) {
for (NSArray *item in result) {
NSArray *products = [item valueForKey:#"ProductDescription"];
[dataArray addObject:products];
[listOfItems addObject:products];
}
}
else {
NSDictionary *jsonDictionary = (NSDictionary *)result;
for(NSDictionary *item in jsonDictionary)
NSLog(#"Item: %#", item);
}
[self performSelector:(#selector(refreshDisplay:)) withObject:(self.productsTableView) afterDelay:1.0];
NSLog(#"Finished");
}
My NSLog is here:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
NSLog(#"Dictionary: %#", dataArray);
return [dataArray count];
}
Simple mixup...
NSString *cellValue = [dataArray objectAtIndex:indexPath.row];
instead of
NSString *cellValue = [listOfItems objectAtIndex:indexPath.row];
You are adding products (which is an NSArray) to listOfItems. Later in cellForRowAtIndexPath, you are saying cellValue (NSString) = [listOfItems objectAtIndex:indexPath.row] (which is potentially an `NSArray'). How would that work?
I'm new to iOS development and Objective-C programming so forgive my "noobiness".
Here's the thing, I have a function that builds an array getting data from a JSON object.
I then have a second function, responsible for filling a tableView with data from contained in my array.
Problem is, the content of this array does not seem accessible from my tableView function, even though the array has been added to my header file and implemented in the main file.
The tableView remains empty...
Do you have any idea why that is?
Here are the functions, thanks a ton for your help!
1) Array building function:
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
[self.responseData appendData:data];
//Get data
NSError *myError = nil;
NSDictionary *res = [NSJSONSerialization JSONObjectWithData:self.responseData options:NSJSONReadingMutableLeaves error:&myError];
//Extract titles
NSMutableArray *myResults = [[NSMutableArray alloc] init];
NSArray *results = [res objectForKey:#"data"];
for (NSDictionary *result in results) {
NSString *title = [result objectForKey:#"colors"];
NSLog(#"colors: %#", colors);
[myResults addObject:colors];
}
self.colorNames = myResults;
}
2) TableView filling function:
// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] autorelease];
}
//Set cell text
NSString *colorString = [self.colorNames objectAtIndex: [indexPath row]];
NSLog(#"%#",colorString);
cell.textLabel.text = colorString;
return cell;
}
are you sure you reload your table view data after receiving your json data? I would suggest a [self.tableView reloadData]; at the end of your connection:didReceiveData: method. Otherwise the method tableView:cellForRowAtIndexPath: will be called only once after you view was loaded.
Cheers,
anka
I guess you must implement something more of the UITableViewDataSource protocol.
You have to supply at least a method tableView:numberOfRowsInSection: returning the actual number of rows your table have, before the tableView:cellForRowAtIndexPath: gets called to fill in the table with your data.
Best wishes
Bruno
Is row a method of indexPath? I think it should be indexPath.row instead of [indexPath row]
okay, here's what I've been scratching my head over for the last few days. I have created a custom cell for my table view. I have created a separate class (customCell.h) for this cell and linked them together in Xcode.
The custom cell has four UIlabels which I have declared in the .h file of the custom cell and linked to the custom cell via storyboard.
I have imported the customCell.h header file into the .h file of my table view controller
I am trying to do a search on twitter, and then populate the table view and custom cell with the details of the various tweets. The issue is I don't know how to link the results of the tweet to the 4 UIlabel outlets in my custom cell.
When I am declaring some of the outlets of the custom cell in my table view implementation file (even though I've imported the .h file of the custom cell) xcode is saying that it does not recognise the name
I've copied the coding below detailing as far as I can get. Any help would be much appreciated. Thanks in advance
- (void)fetchTweets
{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSData* data = [NSData dataWithContentsOfURL:
[NSURL URLWithString: #"THIS IS WHERE MY TWITTER SEARCH STRING WILL GO.json"]];
NSError* error;
tweets = [NSJSONSerialization JSONObjectWithData:data
options:kNilOptions
error:&error];
dispatch_async(dispatch_get_main_queue(), ^{
[self.tableView reloadData];
});
});
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return tweets.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"TweetCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
NSDictionary *tweet = [tweets objectAtIndex:indexPath.row];
NSString *text = [tweet objectForKey:#"text"];
NSString *name = [[tweet objectForKey:#"user"] objectForKey:#"name"];
NSArray *arrayForCustomcell = [tweet componentsSeparatedByString:#":"];
cell.textLabel.text = text;
cell.detailTextLabel.text = [NSString stringWithFormat:#"by %#", name];
return cell;
}
You are creating an instance of the UITableViewCell, which is the default class for tableview cells. In your case, you have to create an instance of your customCell class (which extends the UITableViewCell class). You have to do this in you cellForRowAtIndexPath method:
static NSString *CellIdentifier = #"TweetCell";
customCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if ( cell == nil )
{
cell = [[customCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
// Get the tweet
NSDictionary *tweet = [tweets objectAtIndex:indexPath.row];
I hope this helped you out!
Steffen.