tableView not populating with data from array - ios

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]

Related

Parsing JSON in UITableviewcell

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;
}

iOS program to display database contents in app seperated by tabs

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.

Displaying data in UITableView

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?

Linking a twitter search to a custom tableview cell

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.

Fill UITableView with Facebook albums | IOS

I started to use IOS and the Graph Api some weeks ago. I have problems to fill a UITableView with the albums data that I retrieve from facebook. I make my appdelegete my uitabledatasource and uitabledelegate too I make the following request after the user is logged:
NSString* fql = [NSString stringWithString:#"select object_id, cover_object_id, name, description from album where can_upload=1 and owner=me ()"];
NSMutableDictionary* params = [NSMutableDictionary dictionaryWithObject:fql forKey:#"query"];
[facebook requestWithMethodName:#"fql.query" andParams:params andHttpMethod:#"GET" andDelegate:self];
[theTable reloadData];
And I implement the following to the table:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [self.resultData count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *SimpleTableIdentifier = #"SimpleTableIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier: SimpleTableIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:SimpleTableIdentifier] autorelease];
}
NSUInteger row = [indexPath row]; cell.textLabel.text = [[self.resultData objectAtIndex:row] valueForKey:#"name"];
NSLog(#"the name %#", [[self.resultData objectAtIndex:row] valueForKey:#"name"]);
return cell;
}
And a manage the result like this:
- (void)request:(FBRequest *)request didLoad:(id)result {
if ([result isKindOfClass:[NSArray class]]) {
resultData=result;
[theTable reloadData];
}
NSLog(#"Result of API call: %#", result);
}
I get a correct result of the query but the table never reload the data so it is always empty
First of all, you need to retain resultData in request:didLoad: (use the setter method!).
Secondly, you should check if the table does not try reload the data at all or if something in your table view data source methods goes wrong. If the former, it is likely that theTable is actually nil in request:didLoad: so that the reloadData call has no effect. Check that with the debugger.
If that's not the case, we need more information. Go through the code with the debugger and check for each of the table view data source methods if they get called and where in that flow the processing goes wrong.

Resources