How to instantiate UITableViewCell with custom class in switch section - ios

I need to make a object in the beginning of the cellForRowAtIndexPath to add different cells in it with switch section:
switch (indexPath.section) {
case DetailControllerAddressSection: {
NSString *address = [self addressText];
UITableViewCell *cell;
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
if (IS_OS_7_OR_LATER) {
cell = (CustomDetailCell *) [tableView dequeueReusableCellWithIdentifier:#"AddressCell" forIndexPath:indexPath];
cell.mainLabel.text = address;
cell.detailLabel.text = [self distanceMessageForObjectData:self.objectData];
} else {
UniversalAddressCell *cell = (UniversalAddressCell *) [tableView dequeueReusableCellWithIdentifier:#"UniversalAddressCell" forIndexPath:indexPath];
cell.backgroundView = [self cellBackgroundImageView:indexPath];
cell.mainLabel.text = address;
...
But in this case the cell is the UITableViewCell and I can't get the labels from CustomDetailCell class. How to solve this? The decision is simple I believe but I don't know how to solve it..

The problem is with this: UITableViewCell *cell;
Even though you cast the cell as (CustomDetailCell *) the storage type is still UITableViewCell
what you could do is:
switch (indexPath.section) {
case DetailControllerAddressSection: {
NSString *address = [self addressText];
UITableViewCell *cell;
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
if (IS_OS_7_OR_LATER) {
CustomDetailCell *detailCell = (CustomDetailCell *) [tableView dequeueReusableCellWithIdentifier:#"AddressCell" forIndexPath:indexPath];
detailCell.mainLabel.text = address;
detailCell.detailLabel.text = [self distanceMessageForObjectData:self.objectData];
cell = detailCell;
} else {
UniversalAddressCell *universalCell = (UniversalAddressCell *) [tableView dequeueReusableCellWithIdentifier:#"UniversalAddressCell" forIndexPath:indexPath];
universalCell.backgroundView = [self cellBackgroundImageView:indexPath];
universalCell.mainLabel.text = address;
cell = universalCell;

I guess you'd do typecasting..
[(CustomDetailCell *)cell mainLabel].text = address;

If you have two different NIBs for two cells:
static NSString *simpleTableIdentifier = #"SimpleTableCell";
SimpleTableCell *cell = (SimpleTableCell *)[tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil)
{
switch (indexPath.section) {
case DetailControllerAddressSection:
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"SimpleTableCell1" owner:self options:nil];
cell1 = [nib objectAtIndex:0];
// write here cell1 specific
cell=cell1;
break;
case anotherCase:
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"SimpleTableCell2" owner:self options:nil];
cell2 = [nib objectAtIndex:0];
// write here cell2 specific
cell=cell2;
}
}
return cell;

Related

Add Custom Cell Randomly in UITableView

I have a UITableView which is populated with an NSArray. The array is sorted alphabetically in my table with alphabetized headers.
I am adding a custom cell randomly in my table at every 10th row.
The issue I have is that the custom cell is layering over actually data, so it's not being inserting within the array.
How can I solve this?
Here's what I am doing to insert the custom cell:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
if (indexPath.row % 10 == 10-1) {
CustomAdCell *cell = (CustomAdCell *)[tableView dequeueReusableCellWithIdentifier:#"AdCell"];
if (cell == nil)
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"CustomAdCell" owner:self options:nil];
cell = [nib objectAtIndex:0];
}
return cell;
}
else {
static NSString *cellIdentifier = #"cellIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
// Configure the cell...
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
}
NSString *key = [[[self indexedMembers] allKeys] sortedArrayUsingSelector:#selector(localizedCaseInsensitiveCompare:)][indexPath.section];
self.indexedMembersArray = ((NSMutableArray *)[self indexedMembers][key]);
MemberInfo *currentMember = self.indexedMembersArray[indexPath.row];
cell.textLabel.text = [NSString stringWithFormat:#"%# %#", currentMember.firstName, currentMember.lastName];
return cell;
}

UITableView cell having different identifiers for three different cell design

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"reviews";
static NSString *CellIdentifier1 = #"recipes";
static NSString *CellIdentifier2 = #"easy_tips";
// Configure Cell
NSString *type = [[myaray objectAtIndex:indexPath.row]objectForKey:#"type"];
NSLog(#"types====%#",type);
UITableViewCell *mycell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
if (type == CellIdentifier) {
firstCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
NSLog(#"First type %#", type);
return cell;
}else if (type == CellIdentifier1){
SecondTableViewCell *cell1 = [tableView dequeueReusableCellWithIdentifier:CellIdentifier1 forIndexPath:indexPath];
return cell1;
}else if (type == CellIdentifier2){
ThirdTableViewCell *cell2 = [tableView dequeueReusableCellWithIdentifier:CellIdentifier2 forIndexPath:indexPath];
return cell2;
}
return mycell;
}
I am getting only one cell every time it is first cell .
It is not going to if condition statement.
Thanks in advance for your reply
Change every part you use == to compare string to isEqualToString:
For example:
Change
if (type == CellIdentifier)
To
if([type isEqualToString:CellIdentifier])
Try using Switch Condition rather If and else if
I think it would be better if you consider rethinking the whole logic.
I would do the same thing like this
-(UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *type = [[myaray objectAtIndex:indexPath.row]objectForKey:#"type"];
myCell = (CustomCell *)[tableView dequeueReusableCellWithIdentifier:#"CustomCellid" ];
if(myCell==nil)
{
NSArray *arr= [[NSBundle mainBundle] loadNibNamed:#"CustomCell" owner:self options:nil];
if(types isEqualToString:#"reviews")
{
myCell=[arr objectAtIndex:0];
}
else if(types isEqualToString:#"recipes")
{
myCell=[arr objectAtIndex:1];
}
else if(types isEqualToString:#"easy_tips")
{
myCell=[arr objectAtIndex:2];
}
}
return myCell;
}
Create a UITableViewCell class 'CustomCell'.
Create three UITableViewCells in 'CustomCell.xib'. Each cell for each type, the whole xib will be having the identifier 'CustomCellid'
Then the above code would give you desired result. give a try

how to show different custom cell in a table view in ios

1. in my method in write code example given below -
(UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *simpleTableIdentifier = #"SimpleTableCell";
static NSString *simpleTableIdentifier2 = #"SimpleTableCell2";
if (indexPath.row== 0) {
SimpleTableCell *cell = nil;
cell=(SimpleTableCell *)[tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
}
if (cell == nil)
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"SimpleTableCell" owner:self options:nil];
cell = [nib objectAtIndex:0];
}
if (indexPath.row == 1) {
SimpleTableCell2 *cell2 = nil;
cell2=(SimpleTableCell2 *) [tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier2];
}
if (cell2 == nil)
{
NSArray *nib2 = [[NSBundle mainBundle] loadNibNamed:#"SimpleTableCell2" owner:self options:nil];
cell2 = [nib2 objectAtIndex:0];
}
cell.nameLabel.text = [tableData objectAtIndex:indexPath.row];
cell.thumbnailImageView.image = [UIImage imageNamed:[thumbnails objectAtIndex:indexPath.row]];
cell.prepTimeLabel.text = #"detail";// [prepTime objectAtIndex:indexPath.row];
//cell.imageView.image = [UIImage imageNamed:#"creme_brelee.jpg"];
cell2.nameLabel.text = [tableData objectAtIndex:indexPath.row];
return cell;
}
can any one help me am i write correct code becoz it will give an error
the error is use of undeclear identifier cell and cell2
i dont understand what is this error
it gives the error after making cell2 before cell2 it works perfectly
help me
thanks
It is giving the error because you have declared it like this:
if (indexPath.row== 0) {
SimpleTableCell *cell = nil;
cell=(SimpleTableCell *)[tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
}
and you are using the cell variable outside the local scope of this condition.
Do this:
SimpleTableCell *cell = nil;
if (indexPath.row== 0)
{
cell=(SimpleTableCell *)[tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
}
Also make sure that you have imported the header SimpleTableCell.h.
Hope that helps!
if (indexPath.row == 1) {
SimpleTableCell2 *cell2 = nil;
cell2=(SimpleTableCell2 *) [tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier2];
//This is ok
cell2.nameLabel.text = [tableData objectAtIndex:indexPath.row];
}
//No you cant access outside
cell2.nameLabel.text = [tableData objectAtIndex:indexPath.row];
Here, you have declared cell2 inside the if block. So you can use this variable in this scope only. When you try to access cell2 outside, you will get use of undeclared error.
Undeclared identifier means that you didn't register cell class.
You should do that in viewDidLoad:
-(void)viewDidLoad
{
[self.tableView registerClass:[SimpleTableCell class] forCellReuseIdentifier:#"SimpleTableCell"];
[self.tableView registerClass:[SimpleTableCell2 class] forCellReuseIdentifier:#"SimpleTableCell2"];
}
However, NSStringFromClass approach is better when dealing with cell identifiers:
-(void)viewDidLoad
{
[self.tableView registerClass:NSStringFromClass([SimpleTableCell class]) forCellReuseIdentifier:#"SimpleTableCell"];
[self.tableView registerClass:NSStringFromClass([SimpleTableCell2 class]) forCellReuseIdentifier:#"SimpleTableCell2"];
}
If you didn't register a cell class, dequeueReusableCellWithIdentifier can return nil, as specified in the docs:
This method dequeues an existing cell if one is available or creates a new one
using the class or nib file you previously registered. If no cell is available
for reuse and you did not register a class or nib file, this method returns nil.
Additional note: keep your view controller methods as slim as possibile.
you could try these codes:
- (UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath (NSIndexPath *)indexPath{
static NSString *simpleTableIdentifier = #"SimpleTableCell";
static NSString *simpleTableIdentifier2 = #"SimpleTableCell2";
if (indexPath.row== 0) {
SimpleTableCell *cell = nil;
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];
cell.thumbnailImageView.image = [UIImage imageNamed:[thumbnails objectAtIndex:indexPath.row]];
cell.prepTimeLabel.text = #"detail";// [prepTime objectAtIndex:indexPath.row];
//cell.imageView.image = [UIImage imageNamed:#"creme_brelee.jpg"];
return cell;
}
SimpleTableCell2 *cell2 = nil;
if (indexPath.row == 1) {
cell2 = (SimpleTableCell2 *)[tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier2];
if (cell2 == nil){
NSArray *nib2 = [[NSBundle mainBundle] loadNibNamed:#"SimpleTableCell2" owner:self options:nil];
cell2 = [nib2 objectAtIndex:0];
}
cell2.nameLabel.text = [tableData objectAtIndex:indexPath.row];
}
return cell2;
}
if (indexPath.row== 0) {
SimpleTableCell *cell = nil;
cell=(SimpleTableCell *)[tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil)
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"SimpleTableCell" owner:self options:nil];
cell = [nib objectAtIndex:0];
}
return cell;
}
if (indexPath.row == 1) {
SimpleTableCell2 *cell2 = nil;
cell2=(SimpleTableCell2 *) [tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier2];
if (cell2 == nil)
{
NSArray *nib2 = [[NSBundle mainBundle] loadNibNamed:#"SimpleTableCell2" owner:self options:nil];
cell2 = [nib2 objectAtIndex:0];
}
return cell2;
}
UITableViewCell *commonCell = [tableView dequeueReusableCellWithIdentifier:#"commonToALL"];
if (commonCell == nil) {
commonCell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"commonToALL"];
}
return commonCell;
Try This. This will create two specific cell for index 0 and 1 while two general Cells for remainder as you have 4 rows.
You'd better check you custom cell's tag in SimpleTableCell.xib
whether the tag is 0
and just one custom cell could work like:
(UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *simpleTableIdentifier = #"SimpleTableCell";
if (cell == nil)
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"SimpleTableCell" owner:self options:nil];
cell = [nib objectAtIndex:0];
}
cell.nameLabel.text = [tableData objectAtIndex:indexPath.row];
cell.thumbnailImageView.image = [UIImage imageNamed:[thumbnails objectAtIndex:indexPath.row]];
cell.prepTimeLabel.text = #"detail";// [prepTime objectAtIndex:indexPath.row];
//cell.imageView.image = [UIImage imageNamed:#"creme_brelee.jpg"];
if (indexPath.row == 1) {
[cell.thumbnailImageView.image setHidden:Yes];
[cell.prepTimeLabel.text setHidden:Yes];
}
return cell;
}

Memory warrning tableviewcell

I have two tableviewcell in xib file and I use both of them.
When I use one of them the memory is still 7.3MB, but when I use both memory grow very fast.
Please help me. I don't now what is wrong.
My code is below:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
NSUInteger row = [indexPath row];
NSDictionary *rowData = [self.events objectAtIndex:row];
static NSString *CellIdentifierL = #"LeftCell";
static NSString *CellIdentifierR = #"RightCell";
SampleTableCell *cellLeft = [tableView dequeueReusableCellWithIdentifier:CellIdentifierL];
SampleTableCell *cellRight = [tableView dequeueReusableCellWithIdentifier:CellIdentifierR];
if (cellLeft == nil) {
NSArray* topLevelObjects = [[NSBundle mainBundle] loadNibNamed:#"LeftTableCell" owner:self options:nil];
for (id currentObject in topLevelObjects) {
if ([currentObject isKindOfClass:[SampleTableCell class]]) {
cellLeft = (SampleTableCell *)currentObject;
break;
}
}
}
if (cellRight == nil) {
NSArray* topLevelObjects = [[NSBundle mainBundle] loadNibNamed:#"RightTableCell" owner:self options:nil];
for (id currentObject in topLevelObjects) {
if ([currentObject isKindOfClass:[SampleTableCell class]]) {
cellRight = (SampleTableCell *)currentObject;
break;
}
}
}
return (row%2==0)?cellRight:cellLeft;
}
You need to create only the cell you need. Your code should be like this:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
NSUInteger row = [indexPath row];
NSDictionary *rowData = [self.events objectAtIndex:row];
static NSString *CellIdentifierL = #"LeftCell";
static NSString *CellIdentifierR = #"RightCell";
if (cellLeft == nil) {
SampleTableCell *cellLeft = [tableView dequeueReusableCellWithIdentifier:CellIdentifierL];
NSArray* topLevelObjects = [[NSBundle mainBundle] loadNibNamed:#"LeftTableCell" owner:self options:nil];
for (id currentObject in topLevelObjects) {
if ([currentObject isKindOfClass:[SampleTableCell class]]) {
cellLeft = (SampleTableCell *)currentObject;
break;
}
}
return cellLeft;
}
if (cellRight == nil) {
SampleTableCell *cellRight = [tableView dequeueReusableCellWithIdentifier:CellIdentifierR];
NSArray* topLevelObjects = [[NSBundle mainBundle] loadNibNamed:#"RightTableCell" owner:self options:nil];
for (id currentObject in topLevelObjects) {
if ([currentObject isKindOfClass:[SampleTableCell class]]) {
cellRight = (SampleTableCell *)currentObject;
break;
}
}
return cellRight;
}
return nil;
}
I change to this:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
NSUInteger row = [indexPath row];
NSDictionary *rowData = [self.events objectAtIndex:row];
SampleTableCell *cell;
if(row%2==0){
cell = [[[NSBundle mainBundle] loadNibNamed:#"RightTableCell" owner:self options:nil]objectAtIndex:0];
}else{
cell = [[[NSBundle mainBundle] loadNibNamed:#"LeftTableCell" owner:self options:nil]objectAtIndex:0];
}
cell.labelName.text = [rowData objectForKey:#"name"];
return cell;
}
But I don't know that is good idea?
This is not a good way to do this. You are creating both cells for every row, but you only use one of them. You should also use the newer way to use a xib based cell -- that is, use registerNib:forCellWithReuseIdentifier: in viewDidLoad, to register both nibs. Do your check for odd/even rows first, and dequeue the correct cell (no need to check for nil when using the register method). You do it like this:
- (void)viewDidLoad {
[super viewDidLoad];
[self.tableView registerNib:[UINib nibWithNibName:#"SampleCell1" bundle:nil] forCellReuseIdentifier:#"SampleCell1"];
[self.tableView registerNib:[UINib nibWithNibName:#"SampleCell2" bundle:nil] forCellReuseIdentifier:#"SampleCell2"];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
if (indexPath.row % 2 == 0) {
SampleCell *cell = [tableView dequeueReusableCellWithIdentifier:#"SampleCell1" forIndexPath:indexPath];
// populate cell with data
return cell;
}else{
SampleCell *cell = [tableView dequeueReusableCellWithIdentifier:#"SampleCell2" forIndexPath:indexPath];
// populate cell with data
return cell;
}
}
This is all you need to do. There's no need to check for a nil cell, because dequeueReusableCellWithIdentifier:forIndexPath: is guaranteed to return a valid cell if you either register a nib, or make the cell in a storyboard (in which case you don't need to register anything).

iOS: lldb EXC_BAD_ACCESS Custom Cell

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"LibraryListingCell";
InSeasonCell *cell = (InSeasonCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
[[NSBundle mainBundle] loadNibNamed:#"InSeasonCellView" owner:self options:nil];
cell = [_cell autorelease];
_cell = nil;
}
if(_dataController!=NULL){
Product *productAtIndex = [_dataController objectInListAtIndex:indexPath.row];
// Configure the cell...
if (productAtIndex.name != nil && productAtIndex.week != nil && productAtIndex.image != nil) {
cell.name.text = productAtIndex.name;
cell.week.text = productAtIndex.week;
cell.image.image = productAtIndex.image;
}
}
return cell;
}
Message ERROR for cell.name.text cell.week.text cell.image.text. Pretty sure it is a memory management error. I have retained and released properly to the best of my knowledge. The application will crash upon launch, sometimes it loads everything fine, but when you scroll it crashes. Any help or pointers about memory management is appreciated.
Instead of this:
if (cell == nil) {
[[NSBundle mainBundle] loadNibNamed:#"InSeasonCellView" owner:self options:nil];
cell = [_cell autorelease];
_cell = nil;
}
You sent autorelease message and set it to nil, later you are trying to access that released cell.
I think it should be as:
static NSString *CellIdentifier = #"LibraryListingCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil){
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
}

Resources