Is it correct to initialise a UITableViewCell using initWithCoder? - iphone

I am loading a UITableViewCell using,
[[NSBundle mainBundle] loadNibNamed:#"BlogCell" owner:self options:nil];
cell = blogCell;
self.blogCell = nil;
where blogCell is an outlet to BlogCell.xib
The actual UITableViewCell is of type BlogCell which is a subclass of UITableViewCell.
In my BlogCell class I am using
-(id)initWithCoder:(NSCoder *)aDecoder {
self = [super initWithCoder:aDecoder];
//initialisation of some cell properties here
return self;
}
Is this correct? Is this the way you would tackle initialisation of a cell loaded from a nib?
Thanks

That, or in awakeFromNib.

Related

No Visible View in Custom Table View Cell

I am doing an exercise about tableView and tableViewCell. And I am having some problems with custom view cells.
I have created my own custom tableViewCell with .xib file called as newCellView.xib. I have required .h and .m files and I choose super class as UITableViewCell.
In my view controller called as TableViewController I was creating a table with default cells like this.
- (UITableViewCell *)tableView: (UITableView *)tableView cellForRowAtIndexPath: (NSIndexPath *)indexPath
{
UITableViewCell *cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:nil];
cell.textLabel.text = [showNames objectAtIndex:[indexPath row]];
cell.imageView.image = [UIImage imageNamed:[iconArray objectAtIndex:[indexPath row]]];
return cell;
}
Once I have created my own custom view. I imported newViewCell.h into my viewController and I updated the code like this.
- (UITableViewCell *)tableView: (UITableView *)tableView cellForRowAtIndexPath: (NSIndexPath *)indexPath
{
static NSString *newCellViewString = #"newCellView";
newCellView *cell = [tableView dequeueReusableCellWithIdentifier:newCellViewString];
//newCellView *cell = [[newCellView alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:newCellView];
if (cell == nil)
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"newCellView" owner:self options:nil];
cell = (newCellView *)[nib objectAtIndex:0];
}
But when I run the app I see a blank page, like I have no related view. Maybe I forgot some connections to add. I can't even see empty cells to view. Only a white blank page. Any help would be great. Thanks.
EDIT FOR OTHER FILES
Here are my .h and .m files.
#import <UIKit/UIKit.h>
#interface newCellView : UITableViewCell <UITableViewDelegate>
#property (nonatomic, strong) IBOutlet UILabel *nameLabel;
#property (nonatomic, strong) IBOutlet UIImageView *iconImageView;
#property (retain, nonatomic) IBOutlet UIButton *extendButton;
#end
.m file
#import "newCellView.h"
#implementation newCellView
#synthesize nameLabel;
#synthesize extendButton;
#synthesize iconImageView;
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
// Initialization code
}
return self;
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
[super setSelected:selected animated:animated];
// Configure the view for the selected state
}
- (void)dealloc {
[extendButton release];
[nameLabel release];
[iconImageView release];
[super dealloc];
}
#end
When dealing with custom cell, I'm always trying to encapsulate everything related to the cell in a UITableViewCell subclass (including the NIB / outlets / ..) and use the tableView registerClass: forCellReuseIdentifier: method to tell my table which class to use for its cells.
In your example to do so you could:
In your newCellView.m, add the nib loading in the cell init:
-(id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
// Initialization code
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"newCellView" owner:self options:nil];
self = [nib objectAtIndex:0];
}
return self;
}
Make sure all Outlets connections are correct. (i.e. your UITableViewCell in your Nib is of class NewCellView,..)
Then in the viewDidLoad of your controller you tell your table to use newCellView for its cells:
[yourTableView registerClass:[newCellView class] forCellReuseIdentifier:#"newCellView"];
Finally in the cellForRowAtIndexpath:
newCellView *cell = [tableView dequeueReusableCellWithIdentifier:#"newCellView"];
if (cell == nil)
{
cell = [[NewCellView alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"newCellView]";
}
I think, the problem with your question is that the custom cells are not attached to the custom class cell.
When you create a UITableViewCell class, it does not create a xib along with it.
Then you need to create a xib file, that needs to be attached to the custom class file.
Create an EMPTY NIB file, with no content. Then add a uitablecustomcell through the objects,
and when you do add the new object, GO TO File Inspector and in File Name enter the name newCellView.
Now the custom cells will display EMPTY rows.
Now, add several views to the custom cell and attach those views via IBOutlets created in .h files, namely nameLabel, iconImageView, extendButton.
This is a simple error I have encountered before. You forgot to typecast. it should be:
cell = (newCellView*)[nib objectAtIndex:0];
If this does not resolve your issue make sure you have your xib file set to use the "newCellView" class and not the default "UITableViewCell" class.
Also, if you created a tableview manually and added it as a subview of another view or set it as your view in the loadView method or similar, rather than subclassing UITableViewController make sure you set the frame for the tableview and that you added it as a subview.
You may want to remove the from your newCellView.h class. The delegate for the tableview should not be a view or a subclass of one. Especially not the cell that the tableview will be presenting. The UITableViewController should be receiving the delegate methods.
I found the answer. Everything was working good in my code except the positioning of the cell view's.
Project was using autolayout as a default property. So whenever i see the white page actually cells were out of bounds. I disabled autolayout and set movement properties of the items from size inspector.
Thanks for efforts.

Reusable UIView as a nib file

I created a Custom UIView called BOHeaderView using xib file. I want this BOHeaderView to be loaded in other UIViewController' xibs.
I tried by adding a UIView in one ViewController nib file and change its type to customView. But I am not able to load the custom view. Below is the initialization code of customView.
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self)
{
// Custom initialization
[[NSBundle mainBundle] loadNibNamed:#"BOHeaderView" owner:self options:nil];
}
return self;
}
- (void) awakeFromNib
{
[super awakeFromNib];
// commenters report the next line causes infinite recursion, so removing it
[self customizeHeadView];
}
You can do it like this :
NSArray *nibViews = [[NSBundle mainBundle] loadNibNamed:#"BOHeaderView"
owner:[[BOHeaderView alloc] init]
options:nil];
BOHeaderView *infoView = [nibViews objectAtIndex:0];
infoView.frame = CGRectMake( put your rect here );
[self addSubview:infoView];
EDIT :
Means you are trying to say : Using a custom UIView from multiple view controllers
I had the same problem and I solved it in this way :
I wrote the below code on buttonClick.
RatingView *rateView = [[RatingView alloc] initWithNibName:#"RatingView" bundle:[NSBundle mainBundle]];
rateView.view.frame = CGRectMake(0,45,1024, 648);
[self.view addSubview:rateView.view];
Happy Coding !!
That row with the NSBundle should be in the class in which you want to load the nib. You should write in that class:
CustomView *customView = [[NSBundle mainBundle] loadNibNamed:#"BOHeaderView" owner:self options:nil].lastObject;
It returns an NSArray, that is why you need the lastObjct

Custom UITableViewCell On Autorelease causes a crash in application

I have a custom cell for my table view which I have designed using interface builder. In its .m file I have some code like this to fetch the xib from the bundle for the custom cell.
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
NSArray *nibArray = [[NSBundle mainBundle] loadNibNamed:#"SubItemsCustomCell" owner:self options:nil];
self = [nibArray objectAtIndex:0]; }
return self;
}
Then when I use this cell in my cellForRowAtIndexPath method and pass it an autorelease message
if (!cellForSubItems) {
cellForSubItems = [[[SubItemsCustomCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"SubItemCell"] autorelease];
}
it crashes when i scroll the tableView giving a message,
-[SubItemsCustomCell release]: message sent to deallocated instance 0xed198b0
It never crashed when I made a custom cell using code, but it does here, why is it so??
Also when I dont autorelease it, it runs absolutely fine, but obviously it will have memory leaks.
Kindly Help me out with this one. Thanks In Advance.
EDIT: I am not using ARC.
Your init method looks very wrong.
At the time it is called, an object has already been allocated. Then, you replace that object with something you load from a nib. Here you already leak the old instance, which you should release first. The new object from the nib is autoreleased (see naming conventions), so you should retain it here.
I strongly suggest removing that bogus code altogether. You don't want to manually call alloc/init, just to replace it with something from a nib there. Load from the nib directly.
So yes, your code may leak, but probably not the way you thought of.
try my bellow code for add cell in UITableView
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
SubItemsCustomCell *cell = (SubItemsCustomCell *) [tableView dequeueReusableCellWithIdentifier:nil];
if (cell == nil)
{
NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:#"SubItemsCustomCell" owner:self options:nil];
for (id currentObject in topLevelObjects){
if ([currentObject isKindOfClass:[UITableViewCell class]]){
cell = (SubItemsCustomCell *) currentObject;
break;
}
}
///do something here
}
return cell;
}
i hope this help you...
:)

Programmatically modify a UITableViewCell initialized from a nib?

I am loading a UITableViewCell from a nib using [[NSBundle mainBundle] loadNibNamed:...]. Now I want to do some post-initialization work programmatically, before the tableviewcell get used in my code. Where should I put this code, as I can't seem to do it in the initWithCoder methods, as the label objects in the class are still nil (so can't set anything). When are the UILabels in the tableviewcell initialized in the first place (they are all defined as IBOutlets)?
You should subclass UITableViewCell, and put an awakeFromNib method in it to perform initializations after awaking from the nib.
To keep your code flexible, put this init code in some routine called myInit and call that from awakeFromNib, and from other places where it should be called.
After some struggles I've come up with a slightly different approach for this situation. I subclass UITableViewCell and have an init routine like this:
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
[[NSBundle mainBundle] loadNibNamed:#"MyUITableViewCell" owner:self options:nil];
[self addSubview:self.contentView];
}
return self;
}
where contentView is an IBOutlet containing the cell content. This allows the rest of my code to just invoke this cell as any other cell. (apart from one nasty cast for (MyUITableViewCell*)[tv dequeueReusableCellWithIdentifier:CellIdentifier];)

UITableViewCustomCell

i want to use UITableCustomCell in my application but i am invoking the custom cell from another class.
When i use UITableViewCell then i need to add these lines to call tableviewcells from another class
/*
SurahViewController *aBookDetail = [[SurahViewController alloc]
initWithNibName:#"SurahView" bundle:nil];
self.surahViewController = aBookDetail;
[self.navigationController pushViewController:surahViewController animated:YES];
[aBookDetail release];
*/
but when i use UITableViewCustomCell in my application and i want to invoke custom table view cell from another class then there is no idea of what code to use to call that UITableCustomCell from another class.
Thank you in advance.
I'm doing it with the following code:
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
[[NSBundle mainBundle] loadNibNamed:#"UILogbookTVCell" owner:self options:nil];
cell = tvCell;
tvCell = nil;
}
Note that tvCell is an UITableView IBOutlet. In the UILogbookTVCell.xib the File's Owner is the UITableViewController implementation, and the UITableViewCell element is connected to the tvCell IBOutlet. Therefore the NSBundle loadNibNamed sets the property tvCell, which can then be set to the local cell and cleared.
This is also the official variant as described in the Table View Programming Guide.