Is it possible to have two different UiTableViewCells in one UiTableView? [duplicate] - ios

This question already has answers here:
2 different types of custom UITableViewCells in UITableView
(3 answers)
Closed 9 years ago.
I'm having an issue and would like to know if what I am trying to do is even possible.
I have a ViewController that has a UITableView as a subview. I then loaded a custom cell and it worked fine. However, I needed another custom cell in the same tableview - this second cell has a separate nib as well.
Is this possible?
Two different custom cells in on section in a UITableView?
I did try something like this:
- (UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier1 = #"ContentCell";
static NSString *CellIdentifier2 = #"SpaceCell";
// Space Cell
if (indexPath.row== 0) {
CellSpace *cell = (CellSpace *) [tableViewdequeueReusableCellWithIdentifier:CellIdentifier2];
return cell;
}
// Content cell
else {
CellView *cell = (CellView *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier1];
// Configure cell
return cell;
}
}
However it seems the else statement is never fired and I normally get a crash saying the method returned nil.
UPDATE
I used the advice and code here and came up with this:
#pragma mark - UITableView Delegate Methods
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 160;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return 22;
}
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
-(UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *CellIdentifier1 = #"UsernameCell";
static NSString *CellIdentifier2 = #"PasswordCell";
if(indexPath.row == 0) {
BBUsernameRegistrationCell *cell = (BBUsernameRegistrationCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier1];
if(cell == nil) {
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:CellIdentifier1 owner:self options:nil]; // set properties
cell = nib[0];
}
// set properties
return cell;
}
// Content cell
else {
BBPasswordTableViewCell *cell = (BBPasswordTableViewCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier2];
if(cell == nil) {
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:CellIdentifier2 owner:self options:nil]; // set properties
cell = nib[0];
}
// set properties
return cell;
}
}
However I only see the first Cell in my tableview. If I switch the cells around the second one loads. But not both at the same time. Does anyone have any idea why?

Yes, it is possible..
- (UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier1 = #"ContentCell";
static NSString *CellIdentifier2 = #"SpaceCell";
// Space Cell
if (indexPath.row== 0) {
CellSpace *cell = (CellSpace *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier2];
if(cell == nil) {
cell = [[CellSpace alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier1];
// set properties
}
// set properties
return cell;
}
// Content cell
else {
CellView *cell = (CellView *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier2];
if(cell == nil) {
cell = [[CellView alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier2];
// set properties
}
// set properties
return cell;
}
}
in your custom cell, do something like this in initWithStyle method:
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:#"CellView" owner:self options:nil];
for (id currentObj in topLevelObjects ) {
if ([currentObj isKindOfClass:[CellView class]]) {
self = (CellView*) currentObj;
}
}
return self;
}

Yes it is possible. But before use this dequeueReusableCellWithIdentifier:. Just register your cell and corresponding nib files.
code as..
-(void)initiateCellRegisteration
{
static NSString *CellIdentifier1 = #"ContentCell";
static NSString *CellIdentifier2 = #"SpaceCell";
[self.tableView registerClass:[ContentCell class] forCellReuseIdentifier:CellIdentifier2];
[self.tableView registerNib:[UINib nibWithNibName:CellIdentifier2 bundle:nil] forCellReuseIdentifier:CellIdentifier2];
[self.tableView registerClass:[SpaceCell class] forCellReuseIdentifier:CellIdentifier1];
[self.tableView registerNib:[UINib nibWithNibName:CellIdentifier1 bundle:nil] forCellReuseIdentifier:CellIdentifier1];
}
Call this method in viewDidLoad

If you are using the cell nib then you need little tricky way to get your cell nib like
static NSString *CellIdentifier = #"ProductCell";
IVProductCell *cell = (IVProductCell*)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
NSArray* objects = [[NSBundle mainBundle] loadNibNamed:#"IVProductCell" owner:nil options:nil];
for (id currentObject in objects) {
if ([currentObject isKindOfClass:[IVProductCell class]]){
cell = (IVProductCell*) currentObject;
}
}
}

Related

UITableview with two different custom cells overlapping while scrolling

I have a UITableView with two different custom cells. One will show normal text message and other with some text and image. I am able to use two different custom cells in cellForRowAtIndexPath and able to see two different cells like below
But whenever i scroll the tableview then the cells are overlapping like below.
Below is my code
-(CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath {
//minimum size of your cell, it should be single line of label if you are not clear min. then return UITableViewAutomaticDimension;
return UITableViewAutomaticDimension;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
id cell = [tableView cellForRowAtIndexPath:indexPath];
if ([cell isKindOfClass:[TicketTableViewCell class]]) {
return 171;
} else {
return UITableViewAutomaticDimension;
}
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [chatHistoryArr count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *msgTypeStr = [msgTypeArr objectAtIndex:indexPath.row];
if ([msgTypeStr isEqualToString:#"msg"]) {
static NSString *simpleTableIdentifier = #"ChatConversationTableViewCell";
ChatConversationTableViewCell *cell = (ChatConversationTableViewCell *)[tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil)
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"ChatConversationTableViewCell" owner:self options:nil];
cell = [nib objectAtIndex:0];
}
cell.selectionStyle = UITableViewCellSelectionStyleNone;
cell.chatmsgLabel.text = [chatHistoryArr objectAtIndex:indexPath.row];
cell.timeAndDateMsgLabel.text = [timeAndDateMsgArr objectAtIndex:indexPath.row];
return cell;
}
else{
static NSString *simpleTableIdentifier = #"TicketTableViewCell";
TicketTableViewCell *cell = (TicketTableViewCell *)[tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil)
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"TicketTableViewCell" owner:self options:nil];
cell = [nib objectAtIndex:0];
}
cell.selectionStyle = UITableViewCellSelectionStyleNone;
cell.tktMsgTxtView.text = [chatHistoryArr objectAtIndex:indexPath.row];
cell.ticketDateAndTimeLbl.text =[timeAndDateMsgArr objectAtIndex:indexPath.row];
return cell;
}
}
No issues in showing data or showing different cells, only problem is overlapping. I have already tried the available solutions but no luck. Below is one of them.
adding the below code in cellForRowAtIndexPath but no use.
for(UIView *view in cell.contentView.subviews){
if ([view isKindOfClass:[UIView class]]) {
[view removeFromSuperview];
}
}
Tried a lot to fix the issue but no luck. Any help will be really appreciated.
Change your code of tableViewCell height
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *msgTypeStr = [msgTypeArr objectAtIndex:indexPath.row];
if ([msgTypeStr isEqualToString:#"msg"]) {
return UITableViewAutomaticDimension;
} else {
return 171;
}
}
It will resolve your overlap issue.
Try this once
NSString *CellIdentifier = [NSString stringWithFormat:#"Cell %d",indexPath.row];
UITableViewCell *cell=[self.tableView cellForRowAtIndexPath:indexPath];
if (cell == nil){
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}

Is that possible to create multiple cells in one xib?

I found it can create different cells with different xibs, but I want to know is possible to create different cell in one xib? If possible, what should I can do this?
Here is the code, I know it is wrong code, so can you guys help me to fix it?
- (void)viewDidLoad {
[super viewDidLoad];
[imageTableView registerNib:[UINib nibWithNibName:#"ImageTableViewCell" bundle:nil] forCellReuseIdentifier:#"oneImageTableViewCell"];
[imageTableView registerNib:[UINib nibWithNibName:#"ImageTableViewCell" bundle:nil] forCellReuseIdentifier:#"twoImageTableViewCell"];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
NSString *identifier1 = #"oneImageTableViewCell";
NSString *identifier2 = #"twoImageTableViewCell";
if (indexPath.row % 2 == 0) {
ImageTableViewCell *cell = [imageTableView dequeueReusableCellWithIdentifier:identifier1 forIndexPath:indexPath];
return cell;
} else {
ImageTableViewCell *cell = [imageTableView dequeueReusableCellWithIdentifier:identifier2 forIndexPath:indexPath];
return cell;
}
}
My first idea would be to not do it. But if I had to do it, I guess I'd try building cells by using the old style dequeue, and, to build the initial pool of reusable cells, by manually extracting them from the nib.
So, don't do any cell nib or cell class registration, then in cellForRowAtIndexPath...
NSString *identifier;
NSInteger index;
if (indexPath.row % 2 == 0) {
identifier = #"oneImageTableViewCell";
index = 0;
} else {
identifier = #"twoImageTableViewCell";
index = 1;
}
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier];
if (!cell) {
NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:#"ImageTableViewCell" owner:self options:nil];
cell = topLevelObjects[index];
}
return cell;

Table View Stuck after update

was working in Xcode 4.6 and have a UItableview set up where the cells are populated from an array. When working in 4.6, the view behaved perfectly and was just how I liked it. After the update to 5.1.1, scrolling seems to have been enabled on the table view, the table view is loaded from the bottom of the view and the 3 populated cells at the top are not visible. Sometimes the view will rubber band and not allow me to scroll all the way back up to the top, and sometimes it won't rubber band and will let me. I am fairly new to this, but have tried messing around with auto layout, but to no avail.
Here's my code for the .h
#interface TableViewController : UITableViewController
#property (nonatomic, strong) NSArray *Manufacturers;
#end
Here's my code for the .m:
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
_Manufacturers = #[#"1",
#"2",
#"3"];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
return _Manufacturers.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"TableCell";
TableCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
// Configure the cell...
int row = [indexPath row];
cell.TitleLabel.text = _Manufacturers[row];
return cell;
}
In cellForRowAtIndexPath:
If you are using default UITableViewCell
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"TableCell
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"CellIdentifier"];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"MyIdentifier"];
}
int row = [indexPath row];
cell.textLabel.text = _Manufacturers[row];
return cell;
}
If you are using custom TableViewCell
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *simpleTableIdentifier = #"SimpleTableCell";
SimpleTableCell *cell = (SimpleTableCell *)[tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil)
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"SimpleTableCell" owner:self options:nil];
cell = [nib objectAtIndex:0];
}
cell.nameLabel.text = [tableData objectAtIndex:indexPath.row];
return cell;
}
TableCell is Custom than write below code..
TableCell *cell = (TableCell*)[tableView dequeueReusableCellWithIdentifier:cellIdentifier];
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"TableCell" owner:self options:nil];
cell = [nib objectAtIndex:0];
Otherwise
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
UITableViewCell *cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
Look at this tutorial for custom cell
http://www.appcoda.com/customize-table-view-cells-for-uitableview/

pass data to UITableViewCell iOS

I currently have a tableView with custom cells that I've called AMPFeedbackTableViewCell. The cells load up perfectly fine.
Here is the code:
-(UITableViewCell*) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
//UITableViewCell* cell = [tableView dequeueReusableCellWithIdentifier:#"feedbackCell"];
AMPFeedbackTableViewCell* cell = (AMPFeedbackTableViewCell*) [tableView dequeueReusableCellWithIdentifier:#"feedbackCell"];
if (cell == nil)
{
cell = [[AMPFeedbackTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"feedbackCell"];
cell.currentFeedback = [[AMPFeedback alloc] init];
cell.currentFeedback = [_feedbackArray objectAtIndex:indexPath.row];
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"FeedbackTableCell" owner:self options:nil];
cell = [nib objectAtIndex:0];
}
I'm trying to pass something to the cell before it starts like in this case it's _currentFeedback. The custom cell has a AMPFeedback item and I want it to set it before it loads. So I can use it like this : (NOTE: This is in AMPFeedbackTableViewCell
- (void)awakeFromNib
{
// Initialization code
if (_currentFeedback != nil)
[self loadImages];
}
However, _currentFeedback is always nil. Is there a way I can pass it over then call awakeFromNib?
Thanks in advance
If you are not insist on doing this inside awakefromNib, there's another way (and maybe better) to do this:
in AMPFeedbackTableViewCell.h
#property (strong) AMPFeedBack *currentFeedback;
in AMPFeedbackTableViewCell.m
#synthesize currentFeedback = _currentFeedback;
- (void)setCurrentFeedback:(AMPFeedback *)feedback {
if (feedback==nil) return;
_currentFeedback = feedback;
[self loadImages];
}
and then we can trigger it directly in main code:
-(UITableViewCell*) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
AMPFeedbackTableViewCell* cell = (AMPFeedbackTableViewCell*) [tableView dequeueReusableCellWithIdentifier:#"feedbackCell"];
if (cell == nil) {
cell = [[AMPFeedbackTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"feedbackCell"];
}
cell.currentFeedback = [_feedbackArray objectAtIndex:indexPath.row];
Hope it helps.
You can do initialization and loading of data in the following method of custom uitableview cell
-(id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
// Initialization code
}
return self;
}
and you can load customcell in your tableview
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *eventListCell = #"EventListCell";
EventListCell *cell = (EventListCell *)[tableView dequeueReusableCellWithIdentifier:eventListCell];
if (cell == nil)
{
cell = (EventListCell*)[[[NSBundle mainBundle] loadNibNamed:#"EventListCell" owner:self options:nil] objectAtIndex:0];
// here you can access the custom class public variable to set data .
}
}

Custom cells issue in iOS 5

I've a custom UITableViewCell subclass and I've read that this is supposed to be the correct way of loading custom cells for iOS 5:
- (UITableViewCell *)tableView:(UITableView *)tv cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
CustomCell *cell = [tv dequeueReusableCellWithIdentifier:#"customCell"];
if (cell == nil) {
cell = [[CustomCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"customCell"];
// Configure cell
cell.nameLabel.text = self.customClass.name;
}
return cell;
}
But the label text is not shown when I run the app. However, I also tried this way:
- (UITableViewCell *)tableView:(UITableView *)tv cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tv dequeueReusableCellWithIdentifier:#"customCell"];
if (cell == nil) {
NSArray* views = [[NSBundle mainBundle] loadNibNamed:#"CustomCell" owner:nil options:nil];
for (UIView *view in views) {
if([view isKindOfClass:[UITableViewCell class]])
{
cell = (CustomCell *)view;
}
}
// Configure cell
((CustomCell *)cell).nameLabel.text = self.customClass.name;
}
return cell;
}
This way the label is displayed, but any reuseIdentifier is set in loadNibName: method. What the best way of loading custom cells should be? I need to support iOS 5+. Could the first approach not be working because I'd to configure cell's labels and styles in initWithStyle: method and not in the table view's method?
Thanks!
The error in your code is that cell.nameLabel.text is only set in the if (cell == nil) { ... } case and not generally.
The easiest ways to load custom cells are
Use registerNib:forCellReuseIdentifier: if the cell is defined in a nib file, or
use registerClass:forCellReuseIdentifier: if the cell is created programmatically, or
use a Storyboard and define "CustomCell" as "Prototype Cell" for the table view.
For example (in viewDidLoad):
[self.tableView registerNib:[UINib nibWithNibName:#"CustomCell" bundle:nil] forCellReuseIdentifier:#"customCell"];
Then dequeueReusableCellWithIdentifier
will always return a cell, so that cellForRowAtIndexPath simplifies to
- (UITableViewCell *)tableView:(UITableView *)tv cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
CustomCell *cell = [tv dequeueReusableCellWithIdentifier:#"customCell"];
cell.nameLabel.text = self.customClass.name;
return cell;
}
Just use this code and try.
static NSString *cellIdentifier=#"cell";
YourCustomCell *cell = (YourCustomCell *) [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell == nil)
{
NSString *customeCellName = [NSString stringWithFormat:#"%#",[YourCustomCell class]];
NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:customeCellName owner:self options:nil];
for (id currentObject in topLevelObjects)
{
if ([currentObject isKindOfClass:[UITableViewCell class]])
{
cell = (YourCustomCell *) currentObject;
break;
}
}
}
cell.nameLabel.text = self.customClass.name; // Make sure self.customclass.name have value.
return cell;
Use this code (NewCustomCell is your Custom UITableViewCell class name)...
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
NewCustomCell *cell = (NewCustomCell*)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
NSArray *nib=[[NSBundle mainBundle]loadNibNamed:#"NewCustomCell" owner:self options:nil];
cell=[nib objectAtIndex:0];
}
return cell;
}
Happy coding... :)

Resources