How to load xib file for cell in tableview in iphone - ios

I saw there are lots of resources available on net regarding this question. I have to load a different XIB (UIViewContoller) file for my cell. I have designed my cell looks there and I want to load that design in my cell.
I wrote this code but I am getting an exception.
-[UIView setTableViewStyle:]: unrecognized selector sent to instance 0x6040de0
2011-07-11 14:42:27.461 TableViewTest[2776:207] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[UIView setTableViewStyle:]: unrecognized selector sent to instance 0x6040de0'
And here is my code of loading nib file
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
// Load the top-level objects from the custom cell XIB.
NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:#"loadXibfile" owner:self options:nil];
// Grab a pointer to the first object (presumably the custom cell, as that's all the XIB should contain).
cell = [topLevelObjects objectAtIndex:0];
}
return cell;

You should use UITableViewCell and not UIView in your XIB file.

Here is the solution and it is useful for me and home for you or some else may be.
cell = [[[YourCustomcell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:#"cell"] autorelease];
NSArray *toplavelobject=[[NSBundle mainBundle]loadNibNamed:#"YourCustomcell" owner:self options:nil];
for(id c in toplavelobject)
{
if ([c isKindOfClass:[UITableViewCell class]])
{
cell=(YourCustomcell *) c;
break;
}
}

Though not a direct answer to your issue, I recommend you make use of this UITableViewCellFactory class, it's very convenient:
http://blog.carbonfive.com/2009/07/16/loading-uitableviewcells-from-a-nib-file/

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
NSString *CellIdentifier = [NSString stringWithFormat:#"Cell%d",indexPath.row];
LatestNewsCell *cell = (LatestNewsCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[NSBundle mainBundle] loadNibNamed:#"LatestNewsCell" owner:self options:nil] objectAtIndex:0];
}
}

This is what I did. Again some of the technique is quite awkward and I need improvement.
First I created a new subclass of UITableViewCell. The problem is I do not get an option to check "include" xib. It's as if xib is meant only for UIViewcontroller. I suppose you can create a subclass of UIViewController with XIB and then crate another subclass of UITableViewCell and move the template to your subclass of UIViewController.
Works.
Then I put these function:
#implementation BGCRBusinessForDisplay2
- (NSString *) reuseIdentifier {
return [[self class] reuseIdentifier];
};
+ (NSString *) reuseIdentifier {
return NSStringFromClass([self class]);
};
To initialize I do:
- (BGCRBusinessForDisplay2 *) initWithBiz: (Business *) biz
{
if (self.biz == nil) //First time set up
{
self = [super init]; //If use dequeueReusableCellWithIdentifier then I shouldn't change the address self points to right
NSString * className = NSStringFromClass([self class]);
PO (className);
[[NSBundle mainBundle] loadNibNamed:className owner:self options:nil];
[self addSubview:self.view]; //What is this for? self.view is of type BGCRBusinessForDisplay2. That view should be self, not one of it's subview Things don't work without it though
}
if (biz==nil)
{
return self; //Useful if we only want to know the height of the cell
}
self.biz = biz;
self.Title.text = biz.Title; //Let's set this one thing first
self.Address.text=biz.ShortenedAddress;
The [self addSubview:self.view]; is kind of awkward. It's what other says I should do and it won't work without it. Actually I want self.view to be self, rather than a subView of self. But hei.... Don't know how to do it otherwise.
...
Then I implement this for cellForRowAtIndexPath
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
//[FetchClass singleton].FetchController
if([BGMDCRFetchClass singleton].FetchController.fetchedObjects.count!=0){
BGCRBusinessForDisplay2 *cell = (BGCRBusinessForDisplay2*)[tableView dequeueReusableCellWithIdentifier:[BGCRBusinessForDisplay2 reuseIdentifier]];
if (cell == nil)
{
cell =[BGCRBusinessForDisplay2 alloc];
}
else{
while (false);
}
Business * theBiz=[[BGMDCRFetchClass singleton].FetchController objectAtIndexPath:indexPath];
cell = [cell initWithBiz:theBiz];
return cell;
//return theBiz.CustomCell;
}else{
UITableViewCell * tvc=[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"tvc"];
return tvc;
}
}
Notice that I separate alloc from init. That's kind of awkward. That is why in my - (BGCRBusinessForDisplay2 *) initWithBiz: (Business *) biz if a cell has been initialized before, I simply don't do the upper part of the init. I simply assign values of Business * to the various outlet in the BGCRBusinessForDisplay2.
I someone can improve my answers they are welcome. So far it works.

Related

Register nib for multiple UITableViewCells in a same .Xib file

I have created a .xib file which has more than 2 tableview cells. I used the following code in the viewDidLoad() method for registering nib to reuse cells.
UINib *nib = [UINib nibWithNibName:#"CartTableViewCells" bundle:nil];
[self.tableView registerNib:nib forCellReuseIdentifier:#"Cell0"];
[self.tableView registerNib:nib forCellReuseIdentifier:#"Cell1"];
[self.tableView registerNib:nib forCellReuseIdentifier:#"Cell2"];
And In - [UITableView CellForRowAtIndexPath] method, I used the following code.
cell0 = (CartTableViewCells *)[self.tableView dequeueReusableCellWithIdentifier:#"Cell0"];
if (cell0==nil)
{
cell0 = [[[NSBundle mainBundle] loadNibNamed:#"CartTableViewCells" owner:self options:nil] objectAtIndex:0];
}
But My app crashed with the following error:
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'invalid nib registered for identifier (Cell0) - nib must contain exactly one top level object which must be a UITableViewCell instance'
You can do this, provided you have some way of distinguishing the views in your XIB (tags, custom classes, etc). You don't even need to register the nib – all you have to do is this:
- (UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSInteger cellIndex = 12345;
NSString *cellIdentifier = #"MyAwesomeCell";
// dequeue cell or, if it doesn't exist yet, create a new one from the nib
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (!cell)
{
NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:#"MyNibWithLotsOfCustomCells" owner:self options:nil];
NSUInteger index = [topLevelObjects indexOfObjectPassingTest:^BOOL(id obj, NSUInteger idx, BOOL *stop) {
// if you distinguish the views by class
return [obj isMemberOfClass:NSClassFromString(cellIdentifier)];
// if you distinguish the views by tag
return [(UIView*)obj tag] == cellIndex;
}];
cell = topLevelObjects[index];
}
// etc.
}
It's important to use dequeueReusableCellWithIdentifier: and not dequeueReusableVellWithIdentifier:forIndexPath: (the difference is explained in this thread).

Custom UITableViewCell using xib

I have a custom UITableViewCell which links to a UITableVIewCell xib. When I run the app, I get an error.
I did a lot of searching and I came up with this. When I try dragging from the cells view to the file owner, it seems like the view is not clickable, or drag-able.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"CategorieUITableVIewCell"];
if (cell == nil) {
UIViewController *tempVC = [[UIViewController alloc] initWithNibName:#"CategorieUITableVIewCell" bundle:nil];
cell = (CategorieUITableVIewCell *)tempVC.view;
}
return cell;
}
Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: '-[UIViewController _loadViewFromNibNamed:bundle:] loaded the "CategorieUITableVIewCell" nib but the view outlet was not set.'
Not sure if this is clear enough, but if you have any questions, please ask.
This will work for SURE. You can try this in cellForRowAtIndexPath method.
static NSString *categoryTableIdentifier = #"CategoryUITableViewCell";
CategoryUITableViewCell *cell = (CategoryUITableViewCell *)[tableView dequeueReusableCellWithIdentifier: categoryTableIdentifier];
if (cell == nil)
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"CategoryUITableViewCell" owner:self options:nil];
cell = [nib objectAtIndex:0];
}
cell.CustomedLabel.text=[YourArray objectAtIndex:indexPath.row];
return cell;
And IMPORTANT thing to note is in your Custom cell class you will have to connect the outlet to "Table View Cell" and not the "File's Owner" when you are working with Custom Cell
Please check the identifier matches with the one you specified in your xib. And then just replace your
if (cell == nil) {
UIViewController *tempVC = [[UIViewController alloc] initWithNibName:#"CategorieUITableVIewCell" bundle:nil];
cell = (CategorieUITableVIewCell *)tempVC.view;
}
code to
if (cell == nil) {
cell = [[[NSBundle mainBundle] loadNibNamed:#"CategorieUITableVIewCell" owner:nil options:nil] objectAtIndex:0];
}
Check cell identifier and class name in xib.

UITableViewCell not modifying it's properties

I have a subclass of UITableViewCell with a xib that I want to use as my table view cell. I need to modify the cell's properties on a cell by cell basis. Here is my code. The NSLog reveals that the properties are changed correctly, but when I run the app, the usernameLabel stays the same as the placeholder in the xib file. I'm grateful for any help and happy holidays.
-(UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath: (NSIndexPath *)indexPath {
static NSString *simpleTableIdentifier = #"SimpleTableItem";
// ActivityCell *cell = [tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
LiveCell *cell = [tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil) {
// Load the top-level objects from the custom cell XIB.
NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:#"LiveCell" owner:self options:nil];
// Grab a pointer to the first object (presumably the custom cell, as that's all the XIB should contain).
cell = [topLevelObjects objectAtIndex:0];
}
if (dataLoaded == YES) {
cell.usernameLabel = [[UILabel alloc] init];
NSLog(#"Data Cell Loaded");
PFObject *liveObject = [tableData objectAtIndex:indexPath.row];
cell.usernameLabel.text= liveObject[#"Name"];
NSLog(#"Name Label: %#", cell.usernameLabel.text);
return cell;
}
else {
return cell;
}
}
Consider this code:
cell.usernameLabel = [[UILabel alloc] init];
NSLog(#"Data Cell Loaded");
PFObject *liveObject = [tableData objectAtIndex:indexPath.row];
cell.usernameLabel.text= liveObject[#"Name"];
NSLog(#"Name Label: %#", cell.usernameLabel.text);
return cell;
You made a label and set its text, but so what? You never put it into the interface of the cell. So the label comes into existence, its text is set, and it then vanishes in a puff of smoke.
If the cell already has a usernameLabel in its interface, then it is wrong to replace it with this new one that is not in the interface. If it doesn't already have a usernameLabel, then you need to put this one in the interface. Either way, this code is silly.

Crash when creating custom UITableViewCell

I am trying to create a custom table view cell with a xib but when I call:
CustomReferenceTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
I get the following:
Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<NSObject 0x7aa59c00> setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key
Here is my setup:
- (void)viewWillAppear:(BOOL)animated
{
[self.tableView registerNib:[UINib nibWithNibName:#"CustomReferenceTableViewCell"
bundle:[NSBundle mainBundle]]
forCellReuseIdentifier:#"referenceCell"];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellIdentifier = #"referenceCell";
CustomReferenceTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell == nil) {
cell = [[CustomReferenceTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
}
cell.number.text = #"1";
cell.referenceName.text = #"Name";
cell.reference.text = #"The text of the reference";
return cell;
}
Here is a picture of my connections in interface builder. Also my cellIdentifiers match between class and xib:
I have seen this post here but I still can't seem to get it work.
Help would be greatly appreciated.
Edit
Here is a pic showing setting of custom class. Below that is my initialiser for the tableViewCell:
Here is the header:
#import <UIKit/UIKit.h>
#interface CustomReferenceTableViewCell : UITableViewCell
#property (nonatomic, weak) IBOutlet UILabel *number;
#property (nonatomic, weak) IBOutlet UILabel *referenceName;
#property (nonatomic, weak) IBOutlet UILabel *reference;
#end
And here is the implementation:
#import "CustomReferenceTableViewCell.h"
#implementation CustomReferenceTableViewCell
- (void)awakeFromNib {
// Initialization code
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
[super setSelected:selected animated:animated];
// Configure the view for the selected state
}
#end
I think you are setting the file owner of the cell to your custom cell which you shouldn't do. The way to get things working for a custom cell is,
In your xib, have a Table View Cell component an populate the contents of the cell in its ContentView.
Make your class CustomReferenceTableViewCell as the Custom Class of that cell component.
Now, do NOT register the cell in your tableview; instead do the following in the cellForRowAtIndexPath when your cell is nil after [tableView dequeueReusableCellWithIdentifier:cellIdentifier]; and then register it:
cell = [self.tableView dequeueReusableCellWithIdentifier:cellID];
if(cell == nil) {
[self.tableView registerNib:[UINib nibWithNibName:[#"CustomReferenceTableViewCell" ] bundle:nil] forCellReuseIdentifier:cellID];
NSArray *nibContents;
CustomReferenceTableViewCell *cell;
nibContents = [[NSBundle mainBundle]
loadNibNamed:nibName owner:self options:NULL];
NSEnumerator *nibEnumerator = [nibContents objectEnumerator];
NSObject *nibItem = nil;
while ((nibItem = [nibEnumerator nextObject]) != nil) {
if ([nibItem isKindOfClass:[CustomReferenceTableViewCell class]]) {
cell = (CustomReferenceTableViewCell *)nibItem;
}
}
}
This method has been working out for me for the past 8 months. I have no reasons why it could cause a problem to you.
Try to set your static NSString *cellIdentifier = #"referenceCell"; above #interface
And change registerNib place from WillAppear to viewDidLoad. Also you can change cell creating
CustomReferenceTableViewCell *cell = (CustomReferenceTableViewCell *)[tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell == nil) {
cell = [[[NSBundle mainBundle]loadNibNamed:#"CustomReferenceTableViewCell" owner:self options:nil] lastObject];
}
Just follow my coding for your app
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
CustomCell *cell = (CustomCell *)[tableView dequeueReusableCellWithIdentifier:#"Reuse"];
NSArray *nib=[[NSBundle mainBundle] loadNibNamed:#"CustomCell" owner:self options:nil];
if(cell == nil)
{
cell = [nib objectAtIndex:0];
}
cell.number.text = #"1";
cell.referenceName.text = #"Name";
cell.reference.text = #"The text of the reference";
return cell;
}
Firstly CodingVoldermort's answer helped me get to sort out the issue. I was setting the File's Owner to my custom class which you shouldn't do. This should be left as NSObject.
The reason I thought it needed to be changed was because I couldn't hook up my IBOutlets by holding control and clicking on the tableview image under placeholders and dragging to the appropriate view in the xib.
Instead I needed to go under 'Show the connection inspector' pane and control + click and drag from there to get the connections to work. Then my original posted code would work.
Many thanks for all the responses guys.

iOS: UITableViewCell subclassing with nib, into UIView (not view controller) subclass

I have a custom UIView subclass Leaderboard which itself contains a tableview tblLeaderboard. The interface was created with a xib. Additionally, I have a UITableViewCell subclass LeaderboardCell which also has a xib. I'm having trouble registering the cell in the tableview.
Here's what I tried, first I registered the nib with the tableview:
-(id)initWithCoder:(NSCoder *)aDecoder
{
self = [super initWithCoder:aDecoder];
if (self)
{
leaderInfo = [NSMutableArray array];
tblLeaderboard.dataSource=self;
[tblLeaderboard registerNib:[UINib nibWithNibName:#"LeaderboardCell" bundle:[NSBundle mainBundle]] forCellReuseIdentifier:#"leaderboardCell"];
}
return self;
}
Then when initializing the cell I have:
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"leaderboardCell";
LeaderboardCell *cell = [tableView
dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[LeaderboardCell alloc]
initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:CellIdentifier];
}
//ADDED THIS IN CASE DEFAULT CELL WAS LOADED
cell.textLabel.text = [[leaderInfo objectAtIndex:indexPath.row] objectForKey:#"name" ];
cell.name.text = [[leaderInfo objectAtIndex:indexPath.row] objectForKey:#"name"];
cell.score.text = [[[leaderInfo objectAtIndex:indexPath.row] objectForKey:#"score"] stringValue];
return cell;
}
The cell doesn't load the nib. It just makes a custom cell (the default cell loads the name and score properly, so I know the datasource is working fine).
I'm not sure if I'm getting in trouble here for using a UIView and not a ViewController to control my UITableView?
I don't really have alot of experiences with xibs, but in my old project I did it this way:
static NSString *leaderBoardIdentifier = #"leaderboardCell"; //cell identifier same name as identifier in xib cell's attribute inspector
LeaderboardCell *cell = (LeaderboardCell *)[tableView dequeueReusableCellWithIdentifier:leaderBoardIdentifier];
if (cell == nil)
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:leaderBoardIdentifier owner:self options:nil];
cell = [nib objectAtIndex:0];
}
I have my cell's xib file with h/m files. In my .h I've just connected elements from xib.
initWithStyle and setSelected methods in cell class have default code in them.

Resources