I have two tables in the same class, I need each table contains different data but i have a trouble with the delegate... How can make each table contains a separate delegate? Thanks, sorry for my English.
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
return 1; }
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return [dataTable1 count];
}
-(UITableViewCell *)tableView:(UITableView *)aTableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
CeldaFamilia *cell = (CeldaFamilia *)[aTableView dequeueReusableCellWithIdentifier:#"CeldaFamilia"];
if (!cell) {
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"CeldaFamilia" owner:self options:nil];
cell = [nib objectAtIndex:0];
}
cell.propTextFamilia.text =[dataTable1 objectAtIndex:indexPath.row];
return cell;
}
You can do this by looking at the tableView argument that was passed in. Example:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
if (tableView == self.tableView1) {
return [dataTable1 count];
} else /* tableView == self.tableView2 */ {
return [dataTable2 count];
}
}
With this pattern, you need to put if statements in all of your UITableViewDataSource and UITableViewDelegate methods.
Another way to do it is to make one method that returns the array of data for the table view:
- (NSArray *)dataTableForTableView:(UITableView *)tableView {
if (tableView == self.tableView1) {
return dataTable1;
} else /* tableView == self.tableView2 */ {
return dataTable2;
}
}
Then use that function in each of your data source/delegate methods. Example:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [[self dataTableForTableView:tableView] count];
}
Your tableView:cellForRowAtIndexPath: method might still need to have an if statement, depending on what the data looks like for each table.
However, I recommend you don't use either of those patterns. Your code will be better organized and easier to understand if you make a separate data source/delegate for each table view. You can use two instances of the same class, or you can make two different classes and use one instance of each class, depending on your needs.
If you set the tags of each tableView to different numbers, you can use that to differentiate them.
For example, you can do
tableView1.tag = 1;
tableView2.tag = 2;
Then in your delegate and dataSource methods, you can do:
if (tableView.tag == 1) {
//first table data
}
else if (tableView.tag == 2) {
//second table data
}
You can add other class for second table (secondTable) and implement in it data source and delegate table view protocols. And in your view controller, which contains 2 tables in viewDidLoad :
SecondTable *second=[SecondTable alloc] init];
second.delegate=self;
second.datasource=second;
And your second table would be a object of SecondTable class, and first table you do like always.
Related
I'm having an issue with running two TableViews in the one ViewController.
EDIT:
To make the question a bit more understandable, I've placed the snippet below of the code.
Things that may be relevant:
Both use custom cells.
From what I have done with the debugger, it looks at though it doesn't pass through the following if statement:
if (tableView == self.tblFriendsList){...}
3.Initially I was trying to use a Containment View to add the second UITableViewController, but now I have opted to try using a UITableView.
The containment view (which includes the two tableViews) comes from a NIB.
I have tried both adding the delegate and datasource manually, and through the file's owner.
I have changed the code so that if it doesn't execute the if statement, then it will execute what is required for the other table (which is setting up successfully), but previously it was also working for the first table when I used the example that I have written below. It is the other table that fails to load when both when used as a tableView or when I try adding an entire ViewController to a subview (I've been interchanging between both to try to solve this).
Spelling has been checked on the actual code many-a-time, so I'm more thinking that it may have to do with the fact that it isn't entering the if statement for the one mentioned above.
Most examples I have seen from videos/Stack Exchange have mainly been prior to this year, so I am wondering if there has been an update to practical coding that I have missed.
Sadly I am only doing this for a job for someone wanting an exact replica of their design, or I would have thought of a nicer alternative!
I have attempted all answers so far, but have come up short... although I have seen too many tutorials on this that have succeeded, so I am very unsure about something funny going on...
EDIT AGAIN 11. Even when setting the tableView tag and running an if statement, the debugger still shows the code skipping past the if statement. Even when the reload data method is called, the debugger does not have another break when it should.
Currently, the code sits as this:
For viewDidLoad:
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
self.m_arrVenueList=[[NSMutableArray alloc]init];
self.m_dictCells = [[NSMutableDictionary alloc] init];
[self setNavigationProperties];
[self loadFriendByLocation];
[self setRefreshController];
self.m_dictFriendListCells = [[NSMutableDictionary alloc] init];
self.tblFriendLocation.delegate = self;
self.tblFriendLocation.dataSource = self;
self.tblFriendsList.delegate = self;
self.tblFriendsList.dataSource = self;
[self.tblFriendsList reloadData];
}
For numberOfRowsInSection:
Note: Just one section for each.
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
if (tableView == self.tblFriendsList) {
return [self.arrFriendsList count];
}
// Return the number of rows in the section.
return [self.m_arrVenueList count];
}
For cellForRowAtIndexPath:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
if (tableView == self.tblFriendsList) {
NSDictionary *friends=[self.arrFriendsList objectAtIndex:indexPath.row];
NSString *friendID = [Utility formattedValue:[friends objectForKey:#"user_id"]];
// Configure the cell using friend object...
NSString *sIdentifier = [NSString stringWithFormat:#"TableCell_%ld",(long)friendID];
FriendListVenueCell *cell = (FriendListVenueCell *)[self.m_dictCells objectForKey:sIdentifier];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
if (cell == nil)
{
cell = (FriendListVenueCell*)[Utility getViewFromXib: #"FriendListVenueCell" classname:[FriendListVenueCell class] owner:tableView];
if (indexPath.row%2 != 0)
{
cell.contentView.backgroundColor = UIColorWithRGB(11,21,39);
}
else
{
cell.contentView.backgroundColor = UIColorWithRGB(12,23,32);
}
}
[cell setCellDataForFriend:friends];
[self.m_dictCells setObject:cell forKey:sIdentifier];
return cell;
}
// Configure the cell using friend object...
NSString *sIdentifier = [NSString stringWithFormat:#"TableCell_%ld",(long)indexPath.row];
FriendsAtVenueCell *cell = (FriendsAtVenueCell*)[self.m_dictCells objectForKey:sIdentifier];
if (cell == nil)
{
cell = (FriendsAtVenueCell *)[Utility getViewFromXib:#"FriendsAtVenueCell" classname:[FriendsAtVenueCell class] owner:tableView];
cell.m_FriendViewContrller = self;
[self.m_dictCells setObject:cell forKey:sIdentifier];
if (indexPath.row%2 != 0)
{
cell.contentView.backgroundColor = UIColorWithRGB(11,21,39);
}
else
{
cell.contentView.backgroundColor = UIColorWithRGB(12,23,32);
}
}
cell.delegate=self;
Venue *tempDic=(Venue*)[self.m_arrVenueList objectAtIndex:indexPath.row];
[cell setCellData:tempDic];
if (tempDic.nVenueId == 0)
{
[cell.m_imgLogo setHidden:YES];
[cell.m_imgLogobg setHidden:YES];
[cell.m_btnFollow setHidden:YES];
}
cell.btnFifthImg.tag = indexPath.row;
cell.m_btnFollow.tag = tempDic.nVenueId;
cell.m_RowId= indexPath.row;
cell.selectionStyle = UITableViewCellSelectionStyleNone;
return cell;
}
So far, what I have attempted to do - from what I have read from StackExchange and seen on tutorials - is to have the method cellForRowAtIndexPath have separate cases for each cell and then return that cell.
Examples include
if (tableView == oneTableViewOutlet) {
//load cell
return cell;
} else if (tableView == anotherTableViewOutlet) {
//load cell
return cell;
}
Hopefully this hasn't made the question too long, I am trying to condense it!
EDIT FINISHED
I've watched it with success on a few videos where they have added the delegate and datasource to self for each respective TableView outlet and it has worked from there, but I am having the issue of one outlet loading and not the other.
The above image has me debugging the issue, where I have Stepped Through the execution of the function and it has successfully initiated the first case, but then returns from the function and does not execute for the other TableView.
The code is tricky as I have custom cases in it, but if there are any other thoughts on debugs or references to help that would be appreciated.
In summary:
2 TableViews
Both hooked up to delegate and datasource
2 Custom NIB Cells used for each table
Only one executing
Add
NSLog(#"Table:%#", tableView) at Line 204.
See if it prints two different tableViews.
and Try replacing Line 205 with if([tableView isEqual:self.tblFriendLocation])
Set the tag for your tableview and compare with tag
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
TablevIewCell1 *cell1=[tableView dequeueReusableCellWithIdentifier:#"CellId1"];
TablevIewCell2 *cell2=[tableView dequeueReusableCellWithIdentifier:#"CellId2"];
switch (tableView.tag) {
case 1:
[cell1.textLabel1 setText:[self.arrForTableView1 objectAtIndex:indexPath.row]];
return cell1;
break;
case 2:
[cell2.textLabel2 setText:[self.arrForTableView2 objectAtIndex:indexPath.row]];
return cell2;
break;
default:
break;
}
return nil;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
if (tableView ==self.tableView1)
return self.arrForTableView1.count;
else
return self.arrForTableView2.count;
}
or else
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
TablevIewCell1 *cell1=[tableView dequeueReusableCellWithIdentifier:#"CellId1"];
TablevIewCell2 *cell2=[tableView dequeueReusableCellWithIdentifier:#"CellId2"];
if ([tableView isEqual:self.tableView1]) {
[cell1.textLabel1 setText:[self.arrForTableView1 objectAtIndex:indexPath.row]];
return cell1;
} if ([tableView isEqual:self.tableView2]){
[cell2.textLabel2 setText:[self.arrForTableView2 objectAtIndex:indexPath.row]];
return cell2;
}
return nil;
}
Hope this will help you.
if([tableview isEqual:tblName])
First of all this is how you must check equality. Secondly post all methods so that one can see exactly what is wrong with your code.
I'm having trouble deciding.
I created a model class, and another one as a singleton,
the singleton uses a NSMutableArray and returns a NSArray as a copy.
One of the UITableViewController will show the array of data.
The question is, if I want to show different data on each UITableViewController should i create multiple arrays and methods that save and edit the arrays or is there a better way to do this?
On your UITableViewDataSource methods, you can decide what information to return based on which TableView is calling the method. For example:
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
//Check which tableview is calling
if (tableview == self.tableView1) {
// Return the number of sections for each possible Table
return 1;
} else {
return 2;
}
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
// Return the number of rows in the section.
// If you're serving data from an array, return the length of the array:
if (tableview == self.tableView1) {
// Return the number of sections for each possible Table
return [dataArray1 count];
} else {
return [dataArray2 count];
}
}
And the same for any DataSource/Delegate methods you may need to implement.
Hope that helps!!
This question already has an answer here:
How to make a Sub Table view in a TableViewCell
(1 answer)
Closed 9 years ago.
In one of the cell of a tableView, i want to put another tableView(toyTable for example). Can anyone help me in this? I have created a tableView (main one) and another tableview in my project. Now in my main tableView, i have many cells and in one of the cell, i want that another table(toyTable) to be present in the cell.
Lets say you have two tables.
Make properties for both of them
// This one might be connected as an outlet with your storyboard
#property (nonatomic) IBOutlet UITableViewController *mainTable;
// This one should be in the .m file
#property (nonatomic) UITableViewController *toyTable;
Implement delegate and datasource protocol methods for each.
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
if (tableView == self.mainTable) {
return 2;
} else {
return 1;
}
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if (tableView == self.mainTable) {
return 10;
} else {
return 5;
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (tableView == self.mainTable) {
// If this is the indexPath for the cell that should contain
// the nested table view, initialize your self.toyTable, set
// datasource and delegate etc.
// Else configure your default outer cell
} else {
// Configure the cells of your self.toyTable;
}
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (tableView == self.mainTable) {
// If this is any normal outer cell
return UITableViewAutomaticDimension;
// If this is the outer cell that contains self.toyTable
return some bigger value (if desired)
} else {
// The height of the inner cell
return UITableViewAutomaticDimension;
}
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if (tableView == self.mainTable) {
// If this is the outer cell that contains self.toyTable
// You should ignore the selection
// Else handle it according to your needs
} else {
// Handle click on inner cell
}
}
If you are using a static table view as your mainTable, you can directly drag a table view onto one of your static cells and define prototype cells etc for it.
Putting table view inside table cell is a bad design. Insert toyTable as a section of main table view instead.
In cellForRowAtIndexPath add that table and do the code like this :
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
if (tableView == mainTable) {
//do this for main table
}
else {
//do this for second table
}
}
Why are u doing this because its a bad idea for nesting the tableview instead UITableview already having expand and collapsing property.
Use below link for reference http://www.cocoanetics.com/2011/03/expandingcollapsing-tableview-sections/
So I'm trying to make two tableviews in one view and I'm having some trouble.
I've read some other response on how to do it but they don't exactly help me.
In my .h file I made two outlets for two views calling them myFirstViewText and mySecondViewTex
So in my m files for - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
I want to be able to print out seperate values in each different controller and I'm not too sure since you only return 1 cell?
So far i've Done this
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *CellIdentifier = #"Rx";
static NSString *CellIdentifier2 = #"allergies";
UITableViewCell *cell = [tableView dequeueReusableHeaderFooterViewWithIdentifier:CellIdentifier];
UITableViewCell *cell2 = [tableView dequeueReusableHeaderFooterViewWithIdentifier:CellIdentifier2];
if(!cell){
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
if (!cell2) {
cell2 = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier2];
}
if (tableView == self.myFirstTextView ) {
cell.textLabel.text = #"HI JAZZY";//[RxDict objectAtIndex:indexPath.row];
}
if (tableView == self.mySecondTextView) {
cell.textLabel.text = #"BYE JAZZY";//[RxDict objectAtIndex:indexPath.row];
}
tableView = self.mySecondTextView;
cell2.textLabel.text = #"I love Jazzy :D";
return cell2;
This prints "I love Jazzy" in my first TableView and nothing gets printed in the second one. Why does this happen and how can I fix it?
Thanks :D
This method gets called by all tableViews that have an instance of your class set as their dataSource.
This means you need to check which tableView was asking for cell number so-and-so.
So, your method should basically look like this:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (tableView == rxTableView) {
//prepare and return the appropriate cell for *this* tableView
}
else if (tableView == allergiesTableView) {
//prepare and return the appropriate cell for *this* tableView
}
return nil; //because you don't expect any other tableView to call this method
}
My suggestion would be to set a tag on both of your table views and then in your tableview dataSource methods check for which the tag the table view your are in. So for instance some where in your code you can do:
myFirstTableView.tag = 1;
mySecondTableView.tag = 2;
later when your are in
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (tableView.tag == 1)
cell.textLabel.text = #"HI JAZZY";//[RxDict objectAtIndex:indexPath.row];
if (tableView.tag == 2)
cell.textLabel.text = #"BYE JAZZY";
}
Also if you have 2 tableviews with different sizes you can achieve this like this:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if (tableView.tag == 1)
return 1;
else if (tableView.tag == 2)
return 2;
}
One approach I don't see implemented too often is actually to use a NSObject subclass to act as the delegate and datasource for each table, not the view controller. It removes the need for the "if (tableView == someTable) ..." code, and might make both your view controller and UITableView code maintainable and readable.
You'd create an NSObject subclass for each table. These subclasses would contain the desired implementation of your UITableView datasource and delegate methods. You'd then instantiate one of each in your view controller and hook each up to its appropriate table.
Problem 1:
tableView = self.mySecondTextView;
cell2.textLabel.text = #"I love Jazzy :D";
return cell2;
What you are doing here is always returning cell2, setting its text "I love jazzy :D" so it will always fill the first table view because you would not have set the tableView=mySecondTextView before entering into the method. The delegate is always targeting firstTableView.
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;
Problem 2:
if (tableView == self.myFirstTextView ) {
cell.textLabel.text = #"HI JAZZY";
//[RxDict objectAtIndex:indexPath.row];
//for printing in first table view return cell here like
return cell;
}
if (tableView == self.mySecondTextView) {
cell.textLabel.text = #"BYE JAZZY";
//[RxDict objectAtIndex:indexPath.row];
//for printing in second tableview return cell two here
return cell2;
}
Make sure the table you want to target is set before entering into this function. You can set it in numberofsection method, the view didload method or somewhere else from where you want to show or target table view (like clicking on some button). But you can't set it here.
I need to create a grouped uitableview that includes some sections and possibly different cell types in each sections.
I am trying to create something like old foursquare app, user page (includes 'leaderboard', 'friend suggestions', 'friends', 'stats', 'most explored categories' ... sections).
I am fairly new to ios programming, so that view may not be a grouped uitableview.
What I especially stuck is creating different cells for sections, and finding out which cells are clicked.
My data source will be 2 different NSArray* that consists of different data types, that's why I need different custom cells.
Since you have two different sets of data and you need to display both in different sections, you have to split the data source methods into two.
Basically, choose which dataset you want to be first and off you go.
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if(section)return secondArray.count;
//Essentially, if statements evaluate TRUE and move forward if the inside is 1 or greater (TRUE == 1)
return firstArray.count;
//If the first if statement return hits, then the code will never reach this statement which turns this into a lighter if else statement
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
if(indexPath.section)
{
//do stuff with second array and choose cell type x
}
else
{
//do stuff with first array and choose cell type y
}
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
//Get the cell with: UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
if(indexPath.section)
{
//perform action for second dataset
}
else
{
//perform action for first dataset
}
}
For headers, you can use either of these methods and just keep the same type of styling as above:
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section;
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section;
You can create multiple custom subclasses of UITableViewCell, and in the tableView:cellForRowAtIndexPath: method for your UITableViewDataSource, you can use if-statements to determine what type of cell to use.
For example, here's a rough outline of what I might do:
-(UITableViewCell *)tableView:(UITableView*)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
//First, determine what type of object we're showing
if (indexPath.section == 0) {
//Create and return this cell.
} else if (indexPath.section == 1) {
//Create and return this cell.
}...
}
Here's how you'd implement numberOfRowsInSection:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
if (section == 0) {
return [firstSectionArray count];
} else if (section == 1) {
return [secondSectionArray count];
} ...
}
For didSelectRowAtIndexPath
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
if (indexPath.section == 0) {
ObjectSelected *objectSelected = [firstArray objectAtIndex:indexPath.row];
//Now you've got the object, so push a view controller:
DetailViewController *dvc = [[DetailViewController alloc] init];
dvc.objectSelected = objectSelected;
[self.navigationController pushViewController:dvc];
} else if (indexPath.section == 1) {
//Same thing, just call [secondArray objectAtIndex:indexPath.row] instead!
}
}