Custom UITableViewCell initializer gets error in IOS - ios

I'm using custom cell like that:
PropertyCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
and it's registered as:
[self.tableView registerNib:[UINib nibWithNibName:#"PropertyCell" bundle:nil] forCellReuseIdentifier:#"PropertyCell"];
Class is declared as:
#interface PropertyCell : UITableViewCell <UITextFieldDelegate>
It contains a UITextField in xib and I need to assign a delegate to it on init.
Problem is that:
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
is never called in that scenario.
Which kind of initializer is used by that dequeueing mechanism ?

You are going to want to use initWithCoder or awakeFromNib as posted in this question...
initwithstyle:reuseIdentifier: not called

Make sure to init your cell in the UITableViewDataSource method:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *PropertyCellIdentifier = #"PropertyCell";
PropertyCell *cell = [tableView dequeueReusableCellWithIdentifier: PropertyCellIdentifier];
if (!cell) {
cell = [[PropertyCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier: PropertyCellIdentifier];
}
// configure cell
return cell;
}

Related

UILabel appears multiple times in UITableViewCell

I'm currently creating my UITableViewCells programmatically like so:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Home-Cell" forIndexPath:indexPath];
UILabel *newLabel = [[UILabel alloc] initwithframe:cell.frame];
[newLabel setText:self.data[indexPath.row]];
[cell addSubview:newLabel];
return cell;
}
This seems to create a new UILabel each time the cell is reused though, which I definitely don't want. I tried doing the following:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Home-Cell" forIndexPath:indexPath];
if (cell == nil) {
UILabel *newLabel = [[UILabel alloc] initwithframe:cell.frame];
[cell addSubview:newLabel];
}
[newLabel setText:self.data[indexPath.row]];
return cell;
}
but then the UILabel seems to never be created. Perhaps this is because I'm using prototype cells with Storyboard and thus the cells are never nil?
You have two solutions.
Create a custom table view cell that already has the label.
If you want to add the label in code, don't register a class for the cell. Then the dequeued cell can be nil and you can add the label at that time (like in your 2nd set of code). This also requires using the dequeueReusableCellWithIdentifier method that doesn't also take an indexPath.
You should create a UITableViewCell subclass and add "newLabel" as a property.
The cell is never nil because the method you use to dequeue the table view cell always returns a cell, creating one if it doesn't already exist in the reuse queue.
A better solution would be to create the label in the cell prototype in the storyboard.
This implementation is against MVC architecture where controller managers stuff and do not deal with view. Here, you are trying to add stuff in view from controller. It is suggested to subclass UITableViewCell as below and add your custom UI controls in there
MyTableViewCell.h
#interface MyTableViewCell : UITableViewCell {
}
#property (nonatomic, strong) UILabel *myLabel;
#end
Then you can implement layoutSubviews in your MyTableViewCell.m file to define the look and feel of your cell.
MyTableViewCell.m
- (id)initWithStyle:(UITableViewCellStyle)iStyle reuseIdentifier:(NSString *)iReuseIdentifier {
if ((self = [super initWithStyle:iStyle reuseIdentifier:iReuseIdentifier])) {
self.myLabel = [[UILabel alloc] initWithFrame:<Your_Frame>];
// Set more Label Properties
[self.contentView addSubview:self.myLabel];
}
return self;
}
- (void)layoutSubviews {
[super layoutSubviews];
// Override run time properties
}
Finally use your custom cell like this:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
MyTableViewCell *cell = (MyTableViewCell *)[tableView dequeueReusableCellWithIdentifier:#"Home-Cell" forIndexPath:indexPath];
if (cell == nil) {
cell = [[MyTableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:#"Home-Cell"];
}
cell.myLabel.text = self.data[indexPath.row];
return cell;
}
As a side note, I hope you know that you get textLabel and detailTextLabel free from default UITableViewCell implementation.

Cannot add any content in my custom cell using a .xib file?

I cannot get the content from my custom cell's xib file, the cells are empty, the cell .xib file only contains a UILabel, then the code in the Master class (in a Master-Detail project) is as follow :
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
MyCell *cell = (MyCell*)[tableView dequeueReusableCellWithIdentifier:#"Cell" forIndexPath:indexPath];
//[self configureCell:cell atIndexPath:indexPath];
return cell;
}
Where self configureCell is for Core Data, to test my UILabel, I did not want to get the value from Core Data, so I commented this line.
The "custom class" is set to "MyCell" in the storyboard, the identifier is the same one...
I also tried this in my class MyCell:
- (void)awakeFromNib {
// Initialization code
self.ibLabel.text = #"allo";
}
but my cells are still empty... The height of each cell is also the same in the .xib as in the code...
EDIT #1:
This worked to register the cell custom class:
UINib *cellNib = [UINib nibWithNibName:#"MyCell" bundle:nil];
[self.tableView registerNib:cellNib forCellReuseIdentifier:#"Cell"];
Make sure you register the nib in viewDidLoad:
self.tableView.registerNib(UINib(nibName: "MyCell", bundle: nil), forCellReuseIdentifier: "Cell")
You have to initialize the cell. It might be the first cell and you haven't got one before...
This method dequeues an existing cell if one is available or creates a new one based on the class or nib file you previously registered.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
MyCell *cell;
cell = (MyCell*)[tableView dequeueReusableCellWithIdentifier:#"Cell" forIndexPath:indexPath];
if (cell == nil)
{
cell = [[MyCell alloc] init];
cell.ibLabel.text = #"allo";
}
return cell;
}
Why not do you try in the cell forRow:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
MyCell *cell = (MyCell*)[tableView dequeueReusableCellWithIdentifier:#"Cell" forIndexPath:indexPath];
cell.ibLabel.text = #"allo";
return cell;
If this don't work, you must be sure that "Cell" is also the identifier in the storyboard, and in the storyboard the class is MyCell.
First, a stupid question: Have you implement this method and It's not returning 0 ?
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return 5; // To test
}
Second:
In storyboaard change de backgroundColor of your custom cell, in order to be sure that is this cell painting.

UITableViewCell detailTextLabel doesn't show up even with different cell styles

Here's my code:
- (UITableView *)table {
if (!_table) {
_table = [[UITableView alloc] initWithFrame:CGRectZero style:UITableViewStyleGrouped];
[_table setDelegate:self];
[_table setDataSource:self];
[_table registerClass:[UITableViewCell class] forCellReuseIdentifier:#"Cell"];
}
return _table;
}
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
if (!cell)
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:CellIdentifier];
else
[self configureCell:cell forRowAtIndexPath:indexPath];
return cell;
}
The problem is when I registerClass for my table, it assumes that my cell style is UITableViewCellStyleDefault. So that's why detailTextLabel doesn't show up. I tested it.
Comment out the registerClass line doesn't work because I don't have any CellIdentifier for dequeueReusableCell. So it will throw some exceptions.
If I'm not using dequeue, it works, but it not the best practice.
AFAIK, table cell couldn't change its style after init. So how can I make the detailTextLabel show up ?
The problem is when I registerClass for my table, it assumes that my cell style is UITableViewCellStyleDefault. So that's why detailTextLabel doesn't show up
That is correct. The solution is: do not register UITableViewCell as your class. Register a custom UITableViewCell subclass whose sole purpose in life is that it initializes itself to a different style.
For example, register the MyCell class, which you have defined like this:
#interface MyCell:UITableViewCell
#end
#implementation MyCell
-(id)initWithStyle:(UITableViewCellStyle)style
reuseIdentifier:(NSString *)reuseIdentifier {
self = [super initWithStyle:UITableViewCellStyleValue2 // or whatever style you want
reuseIdentifier:reuseIdentifier];
return self;
}
#end

In UITableViewController template missing TableViewCell allocation

Recently I noticed that when we creates a new Class template, (Xcode -> File -> New -> File) which is a subclass of UITableViewController implementation is partial in cellForRowAtIndexPath method. I pasted the method below.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
// Configure the cell...
return cell;
}
I think statements like (which is missing),
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
is must in implementation. Is this a bug or something else ?
You don't need to create a cell if you are registering a cell in your table view with the method registerNib:forCellReuseIdentifier: or registerClass:forCellReuseIdentifier: or creating a cell within your table view in a xib or storyboard.

custom UITableViewCellStyle

I want to make custom uitableviewcellstyle to make comments in my app. I want uitableviewcell with comment text, number of likes, author's name, date etc...
Have you any ideas?
I've created method, but I don't know how realize it.
My code:
- (UITableViewCell *)getCommentTableCellWithTableView:(UITableView *)tableView commentText:(NSString *)commentText numberOfRows:(NSInteger)numberOfRows numberOfLikes:(NSString *)numberOfLikes date:(NSString *)date writer:(NSString *) writerName {
static NSString *CellIdentifier = #"TitleCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
return cell;
}
I'm sorry I can't find a tutorial with clear steps, but you can search some related posts or questions on this site.
Hope the simple code below could help you.
Here is a doc may helps too, take your time to have a look ;)
http://developer.apple.com/library/ios/#documentation/userexperience/conceptual/TableView_iPhone/TableViewCells/TableViewCells.html
New class inherit from UITableViewCell, CustomCell.h:
(Tips:File->New File->Objective-C class->set class name & choose the subclass UITableViewCell)
#interface MapsListViewCell : UITableViewCell
{
// Add iVars that you want.
}
// Some custom methods
CustomCell.m:
// ...
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
// Initialization code
}
return self;
}
// ...
// Some custom methods
- (void)setAuthorName:(NSString *)name
{
// ...
}
TableViewController.m:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[CategoriesListViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
CategoriesListViewCell * customCell = (CategoriesListViewCell *)cell;
// Set your data:
[customCell setAuthorName:#"God"];
// ...etc.
return cell;
}
For those of us using the newer (iOS 6 and up) UITableView API for dequeueing cells namelydequeueReusableCellWithIdentifier:forIndexPath this is actually guaranteed to return an instantiated cell so we can't perform the nil check and manually call initWithStyle. Therefore the best solution is to subclass UITableViewCell and manually enforce the style in initialisation.
So as an example if we wanted a cell with the UITableViewCellStyleSubtitle style we would create a custom subclass:
#interface ABCSubtitledTableViewCell : UITableViewCell
#end
#implementation ABCSubtitledTableViewCell
- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
return [super initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:reuseIdentifier];
}
#end
And then in our viewDidLoad we would register the appropriate class
[tableView registerClass:[ABCSubtitledTableViewCell class] forCellReuseIdentifier:NSStringFromClass([ABCSubtitledTableViewCell class])];
Making our dequeue method:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
ABCSubtitledTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:NSStringFromClass([ABCSubtitledTableViewCell class]) forIndexPath:indexPath];
cell.textLabel.numberOfLines = 0;
cell.textLabel.text = #"Hello";
cell.detailTextLabel.text = #"World";
return cell;
}

Resources