How to populate multiple table view sections from the same .plist - objective-c

Sorry if this has been discussed already, I couldn't find what I was after..
I have a .plist file which has 2 arrays in it, which are split exactly how I would like my sections split in my table view.
I have no problem getting an array into a table view, but I cant get my head around how to tell the app that I want one array in the first section and the second array in the second section.
My code at the moment to get an array into a table is this (and it works fine):
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
//Create string with reference to the prototype cell created in storyboard
static NSString *CellIdentifier = #"PlayerNameCell";
//Create table view cell using the correct cell type
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
//Create a dictionary containing the player names
NSDictionary *players = (NSDictionary*) [[self Squad] objectAtIndex:[indexPath row]];
//Set the cell text to the player name
[[cell textLabel] setText:(NSString*)[players valueForKey:#"PlayerFullName"]];
//Set the cell detail text to the squad number
[[cell detailTextLabel] setText:(NSString*)[players valueForKey:#"PlayerSquadNumber"]];
return cell;
}
But now I have another table view where I'll need 2 sections, each reading from different arrays.
Any help would be greatly appreciated.
Many thanks

Just do the following:
- (NSInteger)numberOfSectionsInTableView:(UITableView *)aTableView
{
return 2;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellIdentifier = #"PlayerNameCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
if( cell == nil ){
UITableViewCell *cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
}
if( indexPath.section == 0 ){
NSDictionary *players = (NSDictionary*) [self.array1 objectAtIndex:indexPath.row];
cell.textLabel.text = (NSString*)[players valueForKey:#"PlayerFullName"];
cell.detailTextLabel.text = (NSString*)[players valueForKey:#"PlayerSquadNumber"];
} else {
NSDictionary *players = (NSDictionary*) [self.array2 objectAtIndex:indexPath.row];
cell.textLabel.text = (NSString*)[players valueForKey:#"PlayerFullName"];
cell.detailTextLabel.text = (NSString*)[players valueForKey:#"PlayerSquadNumber"];
}
return cell;
}
Set the number of sections to 2. For each section get the different values with [self.array2 objectAtIndex:indexPath.row].
I don't know how you are saving the plist into 2 arrays, but if you need help with that let me know.

Okay, so you have 2 arrays at the top level, and each of those arrays contains arrays, right?
You've got a couple methods you need to adjust. Return the number of top level arrays for the number of sections in the table view. In cellForRowAtIndexPath:, return the correct object for the correct section/row. Something like
[[sectionsArray objectAtIndex:indexPath.section] objectAtIndex:indexPath.row]

Related

objective c - pass array of objects to table view

i need to pass array of class objects
i have class called Student , it has some properties (name , code , account_type ....);
i call method in database to get all students object
Student_array = [data_base_helper selectAllStudents];
i need to show list of student names in table view, i made anther array called names
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [Student_array count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString * cell_identifer = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cell_identifer forIndexPath:indexPath];
// Configure the cell...
if (cell == nil) {
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cell_identifer];
}
for(Student * st in student_array){
[self.names addObject:st.student_name];
}
cell.textLabel.text = [names objectAtIndex:indexPath.row ];
return cell;
}
i find some problem with delete as i delete by index idea how to pass array of objects in table view
The idea is that you don't need to use an "array of names", you can just use your Students array directly, in this way:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [Student_array count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString * cell_identifer = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cell_identifer forIndexPath:indexPath];
// Configure the cell...
if (cell == nil) {
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cell_identifer];
}
Student *student = Student_array[indexPath.row];
cell.textLabel.text = student.student_name;
return cell;
}
When you'll need to delete a student from the tableView, you can easily remove from the array and then update the tableView accordingly, something like that:
[Student_array removeObjectAtIndex:indexPath.row];
[self.tableView deleteRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationFade];
Note that in the code above I'm assuming that you want to delete the object at the given indexPath.row and that Student_array is a NSMutableArray and not a NSArray
ps: you may want to rename Student_array in students since in objective-c it's not a good practice to name objects with a capital letter, nor to use underscores. Likely I would also rename student_name in name since student is just a repetition of the type of the object.
When You Deleted a cell from table delete items for both array Student_array and self.name array corresponding the deleted cell.

UITableView and datasource

I'm trying to add a data source inside a UITableView. I tried the following, but unfortunately it didn't work:
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 8;
}
// 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:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
// Set the data for this cell:
cell.textLabel.text = [_classCellview objectAtIndex:indexPath.row];
cell.detailTextLabel.text = #"One";
cell.detailTextLabel.text = #"Two";
// set the accessory view:
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
return cell;
}
cell.textLabel.text = [_classCellview objectAtIndex:indexPath.row];
You're telling the table that there are 8 sections, but you're not taking the section from the index path into account when you populate the cell. An index path has (in the case of a table view) two values: a section and a row. You need them both to know what cell you're dealing with. So, you're probably getting the same content repeated in each section of your table. (It'd help if you told us exactly what the problem is, though.)

Why is my UITableView not being updated?

Why does my UITableView not update? Here is how I am attempting to update it.
- (void)viewWillAppear:(BOOL)animated
{
NSArray* arrValues = [self.defaults objectForKey:#"values"];
[self.tableScores insertRowsAtIndexPaths:arrValues withRowAnimation:UITableViewRowAnimationNone];
}
arrValues is now an array of NSNumbers. I am sure that it is not empty.
Call [tableScores reloadData]; in - (void)viewWillAppear:(BOOL)animated
Update 1
Also, you need to define arrValues in your header. Each time the viewWillAppear, you are creating a new instance, but you won't be able to use it throughout the rest of your controller. This is the main reason you aren't seeing anything besides at your breakpoint.
Update 2
According to your comment below, you have not implemented cellForRowAtIndexPath: which is how the cell is created. Below is an example, but you may want to search around the net for example projects because this UITableView's 101. There is still a lot more you need to learn when it comes to arrays and tableViews.
Example cellForRowAtIndexPath:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"FriendCellIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
}
cell.textLabel.text = [arrValues objectAtIndex:indexPath.row];
return cell;
}

how is the function called in xcode

im new to xcode and i am doing this code to fill up the table view with annotation titles but the function gets called more than once and the table cells are filled with all repeated values , how is the function called in xcode , how can i stop this function from getting called more than once
- (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] autorelease];
}
NSLog(#"this is a test text ");
NSMutableArray *annotations = [[NSMutableArray alloc] init];
int i=0;
if(indexPath.section == 0)
{
for(iCodeBlogAnnotation *annotation in [map annotations])
{
i++;
NSLog(#"this is the no %d",i);
[annotations addObject:annotation];
}
cell.textLabel.text = [[annotations objectAtIndex:indexPath.row] title];
}
return cell;
}
Any help would be deeply appreciated ,
Thank you for your help in advance
You can't really control when it's called. It's called each time your tableview wants to display a new cell. You use the indexPath to determine what to put in that cell. It's called at least once per cell that's on the screen (sometimes more if the table is scrolled up and down).
You don't need to create the temporary array each time this function is called, just use [map annotations] directly :
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
// There will be one row per annotation
return [[map annotations] count]
}
- (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] autorelease];
}
// Put the text from this annotation into this cell
cell.textLabel.text = [[[map annotations] objectAtIndex:indexPath.row] title];
return cell;
}
I hope I've understood your question. If not, please tell me in the comments below!
It isn't a function, it is a method.
It is called by a table view as the table view draws cells. It will be called once per cell and, sometimes, more than once per cell depending on what the user is doing.
You don't push data into a table view, it asks you for cell contents.
Asking "how can i stop this function from getting called more than once?" indicates that you don't understand table views (it is confusing if you've come from the "push" model of UI programming). Start with the TableView programming guide.
The function is called whenever the UITableView does not already have a UITableViewCell for a particular index path and needs one. Note that it may be called multiple times for an index path, as a result of user scrolling (to save memory, cells that are offscreen may be reused or released) or calls to reloadData and related functions or insertRowsAtIndexPaths:withRowAnimation: and related functions. You cannot (and really do not want to) prevent it from being called more than once.
That said, assuming that [map annotations] returns an ordered collection of some sort that is ordered the same way each time, your code should be doing what you want (even though it is very inefficient). More detail on the problem would be helpful.

3 tables on ipad with different data

Im trying to implement 3 different table views that load 3 different arrays of information,
In some forum I read that I could use the .tag to differentiate the tables and use conditionals to load the data,
I tried
changing the name of the table
in identity /name of the xib to my table,
and use
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath: (NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
//---try to get a reusable cell---
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
//---create new cell if no reusable cell is available---
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
/*
//---set the text to display for the cell---
NSString *cellValue = [listOfMovies objectAtIndex:indexPath.row];
cell.textLabel.text = cellValue; */
if (tableView.tag == 1) {
//Deal with table 1 - contains 5 sections
cell.textLabel.text = [array objectAtIndex:indexPath.row];
} else if (tableView.tag == 2) {
//Deal with table 2 - contains 1 section
cell.textLabel.text = [array2 objectAtIndex:indexPath.row];
}
// cell.textLabel.text = [array3 objectAtIndex:indexPath.row];
else {
cell.textLabel.text = [array objectAtIndex:indexPath.row];
}
return cell;
}
to change the cell content to show the other array
but is not working (long shot!)
so, How to define this .tag for my tables
also, I want the same for row (count) and sections 1
for all the tables,
so shall I just leave them like that??
I have the 3 tables showing the same array at the moment,
thank you so much!
Um, haven't tried this, but I'd be inclined to look into associating each table view with it's own unique UITableViewDataSource instance. That way they do not have to be all coded in the same class and everything becomes simpler. Not sure how you would go about assembling this, but it should be too hard to work out I would think.
I think you're over-complicating things. In one of my apps I have one table view controller for three tables. The interface definition is something like:
#interface TableViewController : UITableViewController <UIGestureRecognizerDelegate> {
IBOutlet UITableView *leftTable;
IBOutlet UITableView *centerTable;
IBOutlet UITableView *rightTable;
...
Then, in each of the delegate methods, I check to see which table it is before performing the relevant action or returning the relevant result. For example:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
if (tableView == leftTable) {
return [self.leftItems count];
} else if (tableView == centerTable) {
return [self.centerItems count];
} else {
return [self.rightItems count];
}
}