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?
Related
I have an array of data. And wr my data are not displaying in the screen. Not sure, what i am missing.
#property NSMutableArray *NotifTotal;
#interface HomeVC ()<UITableViewDelegate, UITableViewDataSource>
#end
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [self.NotifTotal count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:
(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"FilterTableViewCell";
FilterTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
NSDictionary *dict;
dict = [self.NotifTotal objectAtIndex:indexPath.row];
NSLog(#"%#", dict); // data is coming.
NSString* salt = [dict objectForKey:#"salt"];
NSString* name = [dict objectForKey:#"Name"];
NSLog(#"%#%#", name,swerk); // in console i can print the data
cell.sLabel.text = [NSString stringWithFormat: #"%#", salt];
cell.nLabel.text = [NSString stringWithFormat: #"%#", name];
return cell;
}
Why my data is not showing in my screen.I added the delegate, data source also in my screen.Any solution ?
You said "I added the delegate, data source also in my screen" but it is not very clear to me by that you meant conforming your HomeVC to UITableViewDelegate and UITableViewDataSource as your posted code or you actually set the delegate of your UITableView to HomeVC. So here are something you should check:
Set datasource of your UITableView to HomeVC using Interface Builder or following code:
self.tableView.dataSource = self; // I am assuming self == HomeVC instance
Make sure [self.NotifTotal count] > 0.
Make sure it is not about UITableView's configuration issue by adding a break point to cellForRowAtIndexPath and confirm it called.
If it isn't: go back to 2 points above.
If it is: this is UI issue, let's check if your cells's height is near 0 or they have a transparent color and so on. You can use Xcode's View Debugging tool to debug the issue.
Since you haven't mentioned having registered the cell identifier yet, I assume that's the problem. One way to do this is in your storyboard or xib. Select the prototype cell in your tableview, and set the "identifier" field (in the Attributes inspector pane of Interface Builder). Set it to "FilterTableViewCell".
This looks like a xib problem. I added a bit of code in the middle.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"FilterTableViewCell";
FilterTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
//Add this part
if (cell == nil)
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"FilterTableViewCell" owner:self options:nil];
cell = [nib objectAtIndex:0];
}
//end
NSDictionary *dict;
dict = [self.NotifTotal objectAtIndex:indexPath.row];
NSLog(#"%#", dict); // data is coming.
NSString* salt = [dict objectForKey:#"salt"];
NSString* name = [dict objectForKey:#"Name"];
NSLog(#"%#%#", name,swerk); // in console i can print the data
cell.sLabel.text = [NSString stringWithFormat: #"%#", salt];
cell.nLabel.text = [NSString stringWithFormat: #"%#", name];
return cell;
}
I have a plist and I want ot grab only the items which 'Name' string begins with 'A'. I want then display these in my UITableView, along with the 'NameOrigin' included in the item. I have included a screen shot of my plist. Thanks
My code so far, I am able to display all of the plist items, but I would like to filter the items displayed to ones with string 'Name' being with the letter 'A'?
-(NSArray *)content
{
//if (!_content) {
_content = [[NSArray alloc]initWithContentsOfFile:[[NSBundle mainBundle]pathForResource:#"MyPLIST" ofType:#"plist"]];
// }
return _content;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [TableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
cell.textLabel.text = [[self.content objectAtIndex:indexPath.row] objectForKey:#"Name"];
cell.detailTextLabel.text = [[self.content objectAtIndex:indexPath.row] valueForKey:#"NameOrigin"];
return cell;
}
If you want to filter for only elements where Name begins with "A", try this:
NSArray *filteredArray = [self.content filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:#"Name beginswith %#", #"A"]];
While we're at it: you should consider refactoring your code a bit. Re-loading the data from file every time you call [self content] is a bad idea, performance wise. Instead try this:
// Create a property called content in your class extension on the top of the .m file of your table view controller
#interface YourTableViewController ()
#property (nonatomic, strong) NSArray *content;
#end
Next, add this code in your viewDidLoad callback:
_content = [[NSArray alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:#"MyPLIST" ofType:#"plist"]];
and delete the custom content method.
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;
}
i have viewcontroller .h .m and .xib that contain registration form to insert update and delete.
and i have other xib that contain uitableview that show the sqlite data .how can i display ???
i write the code but its gives the error on array of viewcontroller page and other control that are used in viewcontroller.
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [data count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1
reuseIdentifier:CellIdentifier];
}
cell.textLabel.text = [[data objectAtIndex:indexPath.row] valueForKey:#"name"];
cell.detailTextLabel.text = [[data objectAtIndex:indexPath.row] valueForKey:#"salary"];
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
name.text = [[data objectAtIndex:indexPath.row] valueForKey:#"name"];
salary.text = [[data objectAtIndex:indexPath.row] valueForKey:#"salary"];
}
here data is NSArray in viewcontroller.h file gives error here
and also in didSelectRowAtIndexPath method name.text and salary.text gives error because it is the textfield of viewcontroller.
how can i solved it ?????
You have to make sure the data array should be available in otherViewController. For that create a array property in .h file of OtherViewController and while loading this view controller, assign the data array to this property.
Well as you are using SQlite database, you can fetch the data from the database(you'll need to add additional code) in OtherViewController and display it the tableView there.
Also you can't access the private variables of a view controller inside a different view controller. You will have to create properties for them or create public methods.
do it like this.. First create temporary dictionary and than fetch the data from that..
NSDictionary * tmpDictn = [data objectAtIndex:indexPath.row];
cell.textLabel.text = [tmpDictn valueForKey:#"name"];
cell.detailTextLabel.text = [tmpDictn valueForKey:#"salary"];
And same here..
NSDictionary * tmpDictn = [data objectAtIndex:indexPath.row];
name.text = [tmpDictn valueForKey:#"name"];
salary.text = [tmpDictn valueForKey:#"salary"];
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.