Hi I'm new to IOS developement and I created a UITableView which uses custom cells that are created in a nib. Below is my code from my ViewController that is loading the cells however if I scroll up and down 3 times the app crashes because I don't think I'm reusing the cells correctly. I googled around but much of the code/solutions I found seemed to be outdated. My code is below any help is greatly appreciated!
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"CustomCell";
CustomCell *cell = (CustomCell *) [tableView dequeueReusableCellWithIdentifier:#"cellIdentifier"];
if (cell == nil) {
NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:#"CustomCell" owner:self options:nil];
for (id currentObject in topLevelObjects){
if ([currentObject isKindOfClass:[UITableViewCell class]]){
cell = (CustomCell *) currentObject;
break;
}
}
}
cell.TITLE.text = [NSString stringWithFormat:#"\"%#\"", [TITLE objectAtIndex:indexPath.row]];
cell.desc.text = [desc objectAtIndex:indexPath.row];
cell.votes.text = [votes objectAtIndex:indexPath.row];
return cell;
}
change the row
CustomCell *cell = (CustomCell *) [tableView dequeueReusableCellWithIdentifier:#"cellIdentifier"];
to be
CustomCell *cell = (CustomCell *) [tableView dequeueReusableCellWithIdentifier: CellIdentifier];
Go to your CustomCell .xib file in IB, look for the identifier field and set it to CustomCell
You can register the nib for tableView, like :
(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *cellIdentifier = #"CustomCell";
CustomCell *cell = (CustomCell *) [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell == nil) {
[tableView registerNib:[UINib nibWithNibName:#"CustomCell" bundle:nil] forCellReuseIdentifier:cellIdentifier];
cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
}
//...
return cell;
}
Related
I have created custom table view cell that have 2 images on it (initially set to be hidden).
When I render each cell I check some status and set images visible/hidden property.
When I open that table it looks fine when I scroll to the bottom and back to the top first 2-3 cells have both image displayed.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *CellIdentifier = #"myCustomCell";{
OrderCustomCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if(cell == nil){
[tableView registerNib:[UINib nibWithNibName:#"myCustomCell" bundle:nil] forCellReuseIdentifier:CellIdentifier];
cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
}
...
cell.Title.text = #"some value";
...
if(...){
cell.image1.hidden = YES;
cell.image2.hidden = NO;
}
else{
cell.image1.hidden = NO;
cell.image2.hidden = YES;
}
...
Why this could happen?
Is the problem maybe with CellIdentifier.
UPDATE
First try:
OrderCustomCell *cell;
if(cell == nil){
[tableView registerNib:[UINib nibWithNibName:#"myCustomCell" bundle:nil] forCellReuseIdentifier:CellIdentifier];
cell = [tableView dequeueReusableCellWithIdentifier:nil];
}
Second try:
OrderCustomCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if(cell == nil){
[tableView registerNib:[UINib nibWithNibName:#"myCustomCell" bundle:nil] forCellReuseIdentifier:nil];
cell = [tableView dequeueReusableCellWithIdentifier:nil];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *CellIdentifier = #"myCustomCell";
OrderCustomCell *cell = [tableView dequeueReusableCellWithIdentifier:nil];
if(cell == nil){
[tableView registerNib:[UINib nibWithNibName:#"myCustomCell" bundle:nil] forCellReuseIdentifier:CellIdentifier];
cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
}
...
cell.Title.text = #"some value";
...
if(...){
cell.image1.hidden = YES;
cell.image2.hidden = NO;
}
else{
cell.image1.hidden = NO;
cell.image2.hidden = YES;
}
...
Use this as an identifier.
NSString *identifier =[NSString stringWithFormat:#"%d",indexPath.row];
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier];
if (!cell) {
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier];
}
I hope this will resolve your problem. I had same issue, fixed now.
You can use, it works for me.
OrderCustomCell * orderCustomCell = (OrderCustomCell *)[tableView dequeueReusableCellWithIdentifier:nil];
if (orderCustomCell==nil) {
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"OrderCustomCell" owner:self options:nil];
orderCustomCell = [nib objectAtIndex:0];
}
Before I created custom cell for UITableView I used this to render rows:
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if(cell == nil){
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:CellIdentifier];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
}
Then I have created CustomCell with two UILabels in it.
And replace code from above with:
static NSString *CellIdentifier = #"customCell";
OrderCustomCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if(cell == nil){
[tableView registerNib:[UINib nibWithNibName:#"MyCustomCell" bundle:nil] forCellReuseIdentifier:CellIdentifier];
cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
}
But now accessory is not visible.
It shows only at first row and it doesn't look like before.
Is there anything else that I need to do to show accessory when creating custom cell?
Modify your code as below. Set the accesssory Type outside of condition..
static NSString *CellIdentifier = #"customCell";
OrderCustomCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if(cell == nil){
[tableView registerNib:[UINib nibWithNibName:#"MyCustomCell" bundle:nil] forCellReuseIdentifier:CellIdentifier];
cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
}
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
You have set the accessoryType inside the condition if(cell==nil) which calls first time..
Hope it fix the issue..
If you're using storyboard, then you have to register your custom nib in viewDidLoad
- (void)viewDidLoad
{
[super viewDidLoad];
[self.tableView registerNib:[UINib nibWithNibName:#"YourClass" bundle:[NSBundle mainBundle]] forCellReuseIdentifier:#"YourCellIdentifier"];
}
If you're not using storyboard, you have to register it in your cellForRowAtIndexPath
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *identifier = #"YourCellIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier];
if(!cell)
{
cell = [[[NSBundle mainBundle] loadNibNamed:#"YourCustomClass" owner:self options:nil] lastObject];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
}
////
return cell;
}
You have to register your nib in viewDidLoad instead of cellForRowAtIndexPath
- (void)viewDidLoad
{
[super viewDidLoad];
static NSString *CellIdentifier = #"customCell";
[tableView registerNib:[UINib nibWithNibName:#"MyCustomCell" bundle:nil] forCellReuseIdentifier:CellIdentifier];
}
I'm trying to customize a UITableViewCell, but for some reason it's showing up as blank. Is there something obvious I'm doing wrong? I've pulled the menuLabel from the storyboard as an outlet, so it's tied correctly, and the cell in the storyboard is linked to the class "MenuCell".
In my tableview controller
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"MenuCell";
[self.tableView registerClass:[MenuCell class] forCellReuseIdentifier:CellIdentifier];
MenuCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if(cell == nil) {
NSLog(#"creating a new cell");
cell = [[MenuCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:#"MenuCell"];
}
cell.menuLabel.text = #"Hello";
return cell;
}
You can use this
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"MenuCell";
MenuCell *cell = (MenuCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
UINib* customCellNib = [UINib nibWithNibName:#"MenuCell" bundle:nil];
// Register this nib file with cell identifier.
[tableView registerNib: customCellNib forCellReuseIdentifier:CellIdentifier];
cell = (MenuCell*) [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
}
// Whatever you want
retrun cell;
}
Hope this will help. happy coding :P
Use this one ....
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *cellIdentifier = #"MenuCell";
MenuCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell == nil)
{
cell = [[MenuCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
cell = (MenuCell *)[[[NSBundle mainBundle] loadNibNamed:#"MenuCell" owner:self options:nil] objectAtIndex:0];
}
cell.menuLabel.text = #"Hello";
return cell;
}
I Hope it will be helpful.
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... :)
I am using a TableView xib and all the delegates and datasource seem to be running fine.
If I set self.textLabel.text, it displays the generic number of tableviews correctly, but I need to have my custom TableViewCell showing.
I created a HistoryCell.xib that has just a tableviewcell in it.
I created a UITableViewCell class "HistoryCell.h/HistoryCell.m" and it is set as the file owner of HistoryCell.xib.
I connected the UILabels to the HistoryCell.h
UILabel statusLabel
UILabel nameLabel
UILabel timeLabel
In my main ViewController class int he cellForRowAtIndexPath
I am putting in
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"historyCellType";
HistoryCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[HistoryCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
cell.nameLabel.text = #"Donald Duck";
return cell;
}
What am I doing wrong?
Thanks!
You should register the nib like this (probably in viewDidLoad):
[self.tableView registerNib:[UINib nibWithNibName:#"HistoryCell" bundle:nil ] forCellReuseIdentifier:#"historyCellType"];
Then in your cellForRowAtIndexPath method, use this new way where you don't need the if cell == nil clause:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
HistoryCell *cell = [tableView dequeueReusableCellWithIdentifier:#"historyCellType" forIndexPath:indexPath];
cell.nameLabel.text = #"Donald Duck";
return cell;
}
You need to deserialize the actual XIB data:
HistoryCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
NSArray *cellnib = [[NSBundle mainBundle] loadNibNamed:#"HistoryXIBName" owner:self options:nil];
cell = (HistoryCell *)[cellnib objectAtIndex:0];
}
Otherwise it's just using a "Default" cell.
EDIT: Also, if you are using storyboards, dynamic cell prototypes remove the need to create cells from NIB files (in case that's an option for you.)
EDIT The 2nd:
You can try this as well (this assumes you are using ARC):
HistoryCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
HistoryCell *aNewCell = [[HistoryCell alloc] initWithNibName:#"HistoryXIBName" bundle:nil];
cell = (HistoryCell *)*aNewCell.view;
}
There's another method using outlets to your cell in the containing view's XIB file that's a bit more involved that I used to use when iOS4 was current. If the edited version isn't' working for you, I'll dig out an old project and remember how I did it.
When you use tableViewCell with xib, while instantiation load from xib.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"historyCellType";
HistoryCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[NSBundle mainBundle]loadNibNamed:#"HistoryCell"
owner:nil
options:nil]lastObject];
}
cell.nameLabel.text = #"Donald Duck";
return cell;
}
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *cellidentifier=#"cell1";
customcell *cell =
(customcell*)[tableView dequeueReusableCellWithIdentifier:cellidentifier];
if (cell==nil) {
[tableView registerNib:[UINib nibWithNibName:#"Customcell" bundle:nil]
forCellReuseIdentifier:cellidentifier];
cell =
(customcell*)[tableView dequeueReusableCellWithIdentifier:cellidentifier
forIndexPath:[NSIndexPath indexPathForItem:indexPath.row
inSection:indexPath.section]];
}
return cell;
}