Use another UITableView in a UITableViewController - iphone

I have a UITableViewController,with its own tableview.
But I still want to have another UITableView whose Data Source And Delegate are in another Class.
the symptom is: iPhone 4.0 can't show the UITableView , while The iPhone 6.0 Simulator can show this UITableView in a visiable and right way.
NSLog told me UITableView's height is 0.0 when on iPhone.
The Problem is : I will get the second UITableView by
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
and
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section;`
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
doesn't have any response...

You can try this.
Create two objects for UITableView.
numberOfRowsInSection part do this
(NSInteger)tableView:(UITableView *)tblView
numberOfRowsInSection:(NSInteger)section {
if(tableView == tblLog)
return 3; //Or whatever value
else
return 2;
}
CELLFORROWATINDEX part do this.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UILabel *headingLabel;
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:CellIdentifier] autorelease];
cell.backgroundColor = [UIColor whiteColor];
}
if(tableView == tblLog)
{
switch (indexPath.row)
{
case 0:
{
//do something
} break;
case 1:
{
//do something
} break;
}
}
else if (tableView == tblRange)
{
switch (indexPath.row)
{
case 0:
{
//do something
}break;
case 1:
{
//do something
}break;
}
}
return cell;
}
Let me know if that helps

Related

Populating UITableView from NSArray with indexPath.row

I am trying to populate
UITableView in - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath method with an array I have initialized in viewDidLoad method.
self.questionsArray = [NSArray arrayWithObjects:#"Q1",#"Q2",#"Q3",#"Q4",#"Q5",#"Q6",#"Q7",#"Q8",#"Q9",#"Q7",#"Q8",#"Q9",#"Q10",#"Q11"];
I understand how to implement various sections and reusing a cell with an identifier. As most of the examples I have seen, I tried like question.text = [NSString stringWithFormat:#"%d. %#", indexPath.row ,[self.questionsArray objectAtIndex:indexPath.row]];
But I am getting like
0. Q1 1. Q2 2. Q3 3. Q4 4. Q5 5. Q6 0. Q1 2. Q2 ....
Please help to load all questions (NSString) to my TableView. I messing up with indexPath.row. Its very difficult to understand. Any tips for best practices to handle indexPath effectively.
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 2;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
switch (section) {
case 0:
return [self.questionsArray count];
case 1:
return 1;
default:
return 0;
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (indexPath.section == 0) {
static NSString *QuestionCellIdentifier = #"QuestionCellIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:QuestionCellIdentifier];
if (cell == nil) {
[[NSBundle mainBundle] loadNibNamed:#"QuestionCell" owner:self options:nil];
}
cell = questionCell; // IBoutlet
self.questionCell = nil;
}
question.text = [NSString stringWithFormat:#"%d. %#", indexPath.row ,[self.questionsArray objectAtIndex:indexPath.row]];
return cell;
}
else if (indexPath.section == 1){
static NSString *CustomCellIdentifierMore = #"CustomCellIdentifierMore";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CustomCellIdentifierMore];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CustomCellIdentifierMore] autorelease];
cell.accessoryType = UITableViewCellAccessoryCheckmark;
switch (indexPath.row) {
case 0:
cell.textLabel.text=#"Select";
break;
default:
break;
}
}
return cell;
}
return nil;
}
cellForRowAtIndexPath is not guaranteed to load cells in order and will be called to update certain cells. You also need to provide the numberOfRowsInSection method, for example:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
return [self.tableData count];
}
Are your cells displaying properly or is it just the nslog that is producing confusing output?
Try calling reloadData on your tableView after creating questionsArray in viewDidLoad, so like this:
self.questionsArray = [NSArray arrayWithObjects:#"Q1",#"Q2",#"Q3",#"Q4",#"Q5",#"Q6",#"Q7",#"Q8",#"Q9",#"Q7",#"Q8",#"Q9",#"Q10",#"Q11"];
//or whatever your property for the tableview is called.
[self.tableView reloadData];
Your cellForRowAtIndexPath implementation is a little funky. First, the curly brackets for indexPath.section == 0 condition don't match. Second, I don't see where you are setting the text for cell that you are returning. Whatever you are assigning to question.text should be assigned to cell.textLabel.text. Third, for indexPath.section == 1 condition, you are only setting the text when the cell is nil. The table view is pretty smart about cell management. When a cell goes out of view due to scrolling, it will reuse the cell instead of entirely creating a new one. So, whenever you deque a cell, it may not always be nil. So, you should be setting the cell text outside the if (cell == nil) loop.

Combine static and prototype content in a table view

Is there a way to combine static tableview cells (static content) with dynamic tableview cells (prototype content) using storyboard?
I suggest you treat your table as dynamic, but include the cells you always want at the top. In the Storyboard, place a UITableViewController and have it use a dynamic table. Add as many UITableViewCell prototypes to the table as you need. Say, one each for your static cells, and one to represent the variable cells.
In your UITableViewDataSource class:
#define NUMBER_OF_STATIC_CELLS 3
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [self.dynamicModel count] + NUMBER_OF_STATIC_CELLS;
}
and, then
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
if (indexPath.row < NUMBER_OF_STATIC_CELLS) {
// dequeue and configure my static cell for indexPath.row
NSString *cellIdentifier = ... // id for one of my static cells
} else {
// normal dynamic logic here
NSString *cellIdentifier = #"DynamicCellID"
// dequeue and configure for [self.myDynamicModel objectAtIndex:indexPath.row]
}
}
I had a problem, although it was a slight variant of this. I actually wanted to mix dynamic and static cells but in different groups. Meaning group 1 would have static only cells and group 2 would have dynamic cells.
I accomplished this by actually hard coding static cell values (based on their prototype cell identifiers). The dynamic sections would have normal dynamically populated content. Here is some example code in case anyone else has the same issue:
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
if (section == 1){
return #"Dynamic Cells";
}
if (section == 0){
return #"Static Cells";
}
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if (section == 0) {
return 1; //However many static cells you want
} else {
return [_yourArray count];
}
}
-(UITableViewCell*)tableView:(UITableView*)tableView cellForRowAtIndexPath:(NSIndexPath*)indexPath
{
if (indexPath.section == 0) {
NSString *cellIdentifier = #"staticCellType";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
}
cell.textLabel.text = #"some static content";
return cell;
} else if (indexPath.section == 1){
NSString *cellIdentifier = #"dynamicCellType";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
}
cell.textLabel.text = [_yourArray objectAtIndex:indexPath.row];
return cell;
}
return nil;
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 2;
}
Since no one has actually provided a real answer to the problem (using both static and prototype cells in the same table view), I figured I'd chime in.
It can be done!
Create your static cells as you see fit.
For the sections that need a dynamic cell, if you are NOT using standard UITableViewCell type, you'll need to create your custom one in a separate Nib, otherwise you can use the standard ones.
Then implement the following delegates. Basically for each of these delegates, for the static stuff we want to call super, for the dynamic, we return our values.
First, IF you need to selectively show your dynamic section, you'll want to implement the numberOfSectionsInTableView (otherwise you can leave this delegate out):
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
int staticSections = 1;
int dynamicSections = 1;
if (SOME_BOOLEAN) {
return staticSections + dynamicSections;
} else {
return staticSections;
}
}
Then, you need to implement numberOfRowsInSection:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if (section == 1) {
return A_COUNT;
} else {
return [super tableView:tableView numberOfRowsInSection:section];
}
}
Then, you need to implement heightForRowAtIndexPath:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (indexPath.section == 1) {
return 44.0f;
} else {
return [super tableView:tableView heightForRowAtIndexPath:indexPath];
}
}
Then indentationLevelForRowAtIndexPath:
- (NSInteger)tableView:(UITableView *)tableView indentationLevelForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (indexPath.section == 1) {
return 1; // or manually set in IB (Storyboard)
} else {
return [super tableView:tableView indentationLevelForRowAtIndexPath:indexPath]; // or 0
}
}
Finally, cellForRowAtIndexPath:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (indexPath.section == 1) {
SomeObject *obj = self.someArray[indexPath.row];
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"DynamicCell" forIndexPath:indexPath];
cell.textLabel.text = obj.textValue;
return cell;
} else {
return [super tableView:tableView cellForRowAtIndexPath:indexPath];
}
}
You can always make one you your tableviews appear similar to the static table but define it in code. Set the sections, amount or rows per section, headers etc. through the delegate methods.
Unfortunately, this is not possible since static table views must be in a UITableViewController and that only allows one tableview.
What you need to do is make three more dynamic UITableviewCell's and load them individually for the first three rows where you want the static content.
If you aren't sure how to do this, let me know and I can find some code.
You can't have one tableview be static and the other dynamic in the same view controller so you will need to make them both dynamic. In the first tableview you will configure the cells in code on initializing the view controller never update them.
Add a UIViewController to your storyboard.
Add two Table Views (Not
TableViewControllers) to the UIView Controller.
Select each tableView and configure both for dynamic cells.
Build and attach your view controller. 2 tableview on a single view explains that step.
As another option you can achieve a similar look by embedding your dynamic tableview in part of a view similar to the link in step 4 and then do whatever you wanted to in the rest of the view to setup what you were planning to do with static cells by using scrollviews, labels, and buttons.
You could also create buttons (one for each static cell you have) that are styled like your cells and place them in the tableHeaderView or tableFooterView of the UITableView; those buttons are just views after all.
You'll need to add some logic for making selections on the buttons vs. the cells so it maintains the usual look and feel.
Of course, this assumes that you want to insert static cells into your table view at the top or bottom of the table.
One way to have dynamic content in a static table view is to clone cells where additional rows are needed.
For the dynamic section of my table view, I lay out one or more cells in Interface Builder. At runtime, I can clone those by archiving using NSCoder and then unarchiving.
It works, but is not necessarily prettier than starting with a dynamic prototype table view and creating static rows from there.
It fails with standard table view cells. The lazily created text labels are not laid out correctly. Hence I used UITableViewCell subclasses where I take care of archiving and unarchiving subviews.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (indexPath.section == kContactsSection) {
NSArray *contacts = self.contacts;
Contact *contact = [contacts objectAtIndex:indexPath.row];
NSString *name = contact.name;
NSString *role = contact.role;
if ([role length] == 0) {
NNContactDefaultTableViewCell *cell = (id)[tableView dequeueReusableCellWithIdentifier : #"contactDefault"];
if (cell == nil) {
NNContactDefaultTableViewCell *template = (id)[super tableView : tableView
cellForRowAtIndexPath :[NSIndexPath indexPathForRow:0 inSection:kContactsSection]];
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:template];
cell = [NSKeyedUnarchiver unarchiveObjectWithData:data];
}
cell.contactTextLabel.text = name;
return cell;
}
else {
NNContactDetailTableViewCell *cell = (id)[tableView dequeueReusableCellWithIdentifier : #"contactDetail"];
if (cell == nil) {
NNContactDetailTableViewCell *template = (id)[super tableView : tableView
cellForRowAtIndexPath :[NSIndexPath indexPathForRow:1 inSection:kContactsSection]];
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:template];
cell = [NSKeyedUnarchiver unarchiveObjectWithData:data];
}
cell.contactTextLabel.text = name;
cell.contactDetailTextLabel.text = role;
return cell;
}
}
return [super tableView:tableView cellForRowAtIndexPath:indexPath];
}
In the above example I have two cell types. Both laid out in Interface Builder as part of a static table view.
To get dynamic content in one section, I also need to override the following methods:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if (section == kContactsSection) {
NSArray *contacts = self.contacts;
NSUInteger contactCount = [contacts count];
return contactCount;
}
return [super tableView:tableView numberOfRowsInSection:section];
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSInteger section = indexPath.section;
NSInteger row = indexPath.row;
if (section == kContactsSection) {
return [super tableView:tableView heightForRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:kContactsSection]];
}
return [super tableView:tableView heightForRowAtIndexPath:indexPath];
}
- (CGFloat)tableView:(UITableView *)tableView indentationLevelForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSInteger section = indexPath.section;
if (section == kContactsSection) {
CGFloat indentation = [super tableView:tableView indentationLevelForRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:kContactsSection]];
return indentation;
}
CGFloat indentation = [super tableView:tableView indentationLevelForRowAtIndexPath:indexPath];
return indentation;
}

cellForRowAtIndexPath returning custom cell?

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
// ...
PlanetTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"PlanetCell_ID"];
return cell;
}
If your creating a custom UITableViewCell (in this case PlanetTableViewCell) is it acceptable to return that object via a method returning (UITableViewCell *), or is there something else I should be doing?
If your creating a custom UITableViewCell (in this case PlanetTableViewCell) is it acceptable to return that object via a method returning (UITableView *), or is there something else I should be doing?
You possibly meant:
to return that object via a method returning (UITableViewCell*),
If so, then it is perfectly legal and reasonable.
Indeed, your PlanetTableViewCell being derived from UITableViewCell, all instances of PlanetTableViewCell are also of the type UITableViewCell (is-a relationship in OOP).
Yes, this is the correct way to return the cell.
But you should also be checking to see if your "dequeue" is returning a valid cell object. If not, you'll need to create one.
This method is also where you should be configuring your cell with title, accessories, etc.
Sample code:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
// ...
PlanetTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"PlanetCell_ID"];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
cell.titleLabel.text = #"Cell Title";
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
return cell;
}
Using custom cell
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *simpleTableIdentifier;
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
{
simpleTableIdentifier = #"dashboard_logintimeCell_ipad";
}
else
{
simpleTableIdentifier = #"dashboard_logintimeCell";
}
dashboard_logintimeCell *cell = (dashboard_logintimeCell *)[tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil)
{
NSArray *nib =[[NSBundle mainBundle]loadNibNamed:simpleTableIdentifier owner:self options:nil];
cell = [nib objectAtIndex:0];
}
/*here you cell object get
like
cell.lable.text=#"yourlabeltext";
*/
cell.backgroundColor=[UIColor clearColor];
return cell;
}

how to remove all rows of a tableView

Can anyone tell me that how to remove all rows of a tableView
Clear the datasource (for example [dataSourceMutableArray removeAllObjects]) and reload the table ([tableView reloadData])
I think you can remove all values in dataSource of tableView? Then reload the tableView
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 0;
}
// Customize the number of rows in the table view.
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return 0;
}
or specify return nil; instead of return cell; in cellForRowAtIndextPath function
or you can remove all values in array in cellForRowAtIndexPath like this
- (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];
}
// Configure the cell.
// remove below line
//cell.textlabel.text=[array objectAtIndex:indextPath];
return cell;
}

table view next results

How it is being implemented in table view? To limit the results display in the table view, I need to display eg 10 results, then at the last part of the table cell there's the "next results" part when selecting would load/insert the next set of data into the table view.
Pls. advise me. Thanks
You can make a 2 section UITableView...
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 2;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if (indexPath.section == 0)
return 10;
else {
return 1;
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableView *cell;
if (indexPath.section == 0)
cell = (UITableViewCell*)[tableView dequeueReusableCellWithIdentifier:#"normalCell"];
else
cell = (UITableViewCell*)[tableView dequeueReusableCellWithIdentifier:#"nextCell"];
if (!cell) {
if (indexPath.section == 0)
cell = [[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:#"normalCell"];
else
cell = [[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:#"nextCell"];
}
if (indexPath.section == 0) {
// Set your normal cells
} else {
// Set your next cell
}
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if (indexPath.section == 0) {
// your normal cells here
} else {
// your next cell here
}
}
Of course this is not the only solution, but it works...