i'm using custom cell i learned in (This site). It's work in my old app but in this app i dont know why it's haven't work, when i run the above code he stuck with green error in line (NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:#"CustomCell" owner:self options:nil];).
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
CellIdentifier = #"CustomCell";
PCustomCell *cell = [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 = (PCustomCell *) currentObject;
break;
}
}
}
P2Dict = [P2Rows objectAtIndex: indexPath.row];
cell.Contracts.text = [P2Dict objectForKey:#"Contracts"];
return cell;
}
http://ar2.co/SS2.png
custom cell xib .file take a tablecell.and in custom.m file implemented .and In view controller set the whole tableview through viewcontroller xib or programmatically .as ur choice .and set the delegate and datasourece methods.in datasource method written custom cell.code written below
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Custom";
CustomTableCell *cell = (CustomTableCell *) [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (!cell)
{
UINib *nib = [UINib nibWithNibName:#"CustomTableCell" bundle:nil];
NSArray *arr = [nib instantiateWithOwner:nil options:nil];
cell = [arr objectAtIndex:0];
}
cell.textLabel.text =[arr objectAtIndex:indexPath.row];
}
Did you have UITableviewCell(PCustomCell) at CustomCell.xib?
You should show screenshot of the error here. It's will be helpful.
Your error states: "Could not load NIB in bundle named "CustomCell"". So there lies your problem.... what is your xib named?
refer a following process. How to create a custom table cell is one kind of.
VocaTableCell is my case. make a your CustomTableCell.
#import <UIKit/UIKit.h>
#interface VocaTableCell : UITableViewCell
{
UILabel *vocaLabel;
}
#property (nonatomic, retain) IBOutlet UILabel *vocaLabel;
#end
#import "VocaTableCell.h"
#implementation VocaTableCell
#synthesize vocaLabel;
- (void)dealloc {
[vocaLabel release];
[super dealloc];
}
#end
Below code refer Befoe, Are you correctly make a customTableCell? below list check plz.
There are several ways to create about customTablecell.
My manner is very popular.
CustomTabelCell of File's Owner should be a NSObject.
(Very Important Default is Maybe UITableCell. You Must be a change File's Owner NSObject(NSObject mean is id type!))
CustomTableCell link a Object Class a your CustomTableCell Class.
Referencing Outlets link Not File's Owner, must be Your Directly link a CustomTableCell.
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Custom";
CustomTableCell *cell = (CustomTableCell *) [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (!cell)
{
UINib *nib = [UINib nibWithNibName:#"CustomTableCell" bundle:nil];
NSArray *arr = [nib instantiateWithOwner:nil options:nil];
cell = [arr objectAtIndex:0];
}
cell.textLabel.text =[arr objectAtIndex:indexPath.row];
}
Related
I have this code:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *simpleTableIdentifier = #"BSTGListCell";
BSTGListCell *cell = (BSTGListCell *)[tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil)
{
cell = [[[NSBundle mainBundle] loadNibNamed:#"BSTGListCell" owner:self options:nil] objectAtIndex:0];
}
PFObject* currentEl = [self.tableData objectAtIndex:indexPath.row];
cell.title.text = [currentEl objectForKey:#"Name"];
cell.description.text = [currentEl objectForKey:#"Address"];
return cell;
}
I am getting "message sent to deallocated instance" when scrolling down the table view which is added as a subview.
Zombie inspector says the accessed object is retained here:
cell = [[[NSBundle mainBundle] loadNibNamed:#"BSTGListCell" owner:self options:nil] objectAtIndex:0];
and probably released by ARC.
Why this happens and how I can prevent it?
You really shouldn't do it this way. The way to use cell from a nib is to register the nib, probably in viewDidLoad, like this:
UINib *nib = [UINib nibWithNibName:#"BSTGListCell" bundle:nil];
[self.tableView registerNib:nib forCellReuseIdentifier:#"BSTGListCell"];
Then in your cellForRowAtIndexPath, use dequeueReusableCellWithIdentifier:forIndexPath: and no if(cell == nil) clause.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
BSTGListCell *cell = (BSTGListCell *)[tableView dequeueReusableCellWithIdentifier:#"BSTGListCell" forIndexPath:indexPath];
PFObject* currentEl = [self.tableData objectAtIndex:indexPath.row];
cell.title.text = [currentEl objectForKey:#"Name"];
cell.description.text = [currentEl objectForKey:#"Address"];
return cell;
}
The actual problem with your code is that loadNibNamed:owner:options, returns an array, and you have to get the one object out of that array before you assign it to cell. But, the way I showed is a more efficient way to do this anyway.
My problem was something with the dequeueReusableCell line, i took it out like this link did and mine works now
I am loading a custom cell into a table view, and notice that my cell is not being re-used correctly. I am using a NSFetchedResultsController to pull the results from Core Data.
I am loading the cell from a nib. The cell identifier is setup in interface builder. The cells appear to get re-used because I am not creating a new cell everytime I scroll the table. However, the data is not being displayed correctly on the cells.
// BeerCell.h
#interface BeerCell : UITableViewCell
#property (nonatomic, strong) IBOutlet UIImageView *beerImage;
#property (nonatomic, strong) IBOutlet UILabel *displayBeerName;
#property (nonatomic, strong) IBOutlet UILabel *displayBeerType;
#end
// BeerCell.m
#implementation BeerCell
#synthesize beerImage;
#synthesize displayBeerName;
#synthesize displayBeerType;
#end
// Code where i'm setting up the cells for the tableView
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"BeerCell";
BeerCell *cell = (BeerCell *) [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:#"BeerCell" owner:self options:nil];
for (id currentObject in topLevelObjects){
if ([currentObject isKindOfClass:[UITableViewCell class]]){
cell = (BeerCell *) currentObject;
break;
}
}
[self configureCell:cell atIndexPath:indexPath];
}
return cell;
}
- (void)configureCell:(BeerCell *)cell
atIndexPath:(NSIndexPath *)indexPath
{
Beer *beer = (Beer *) [self.fetchedResultsController objectAtIndexPath:indexPath];
cell.displayBeerName.text = beer.name;
}
Take the configureCell function call outside the if block.
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"BeerCell";
BeerCell *cell = (BeerCell *) [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:#"BeerCell" owner:self options:nil];
for (id currentObject in topLevelObjects){
if ([currentObject isKindOfClass:[UITableViewCell class]]){
cell = (BeerCell *) currentObject;
break;
}
}
}
[self configureCell:cell atIndexPath:indexPath];
return cell;
}
I've been searching a lot but didn't find anything useful related to multiple custom rows, I need to create a settings tableView for my app,in which I need to load the rows from xib files,like:
ROW 1 =>> XIB 1.
ROW 2 =>> XIB 2.
ROW 3 =>> XIB 3.
ROW 4 =>> XIB 4.
My present code:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell=nil;
//We use CellType1 xib for certain rows
if(indexPath.row==0){
static NSString *CellIdentifier = #"ACell";
cell =(ACell*) [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if(cell==nil){
NSArray *nib= [[NSBundle mainBundle] loadNibNamed:#"ACell" owner:self options:nil];
cell = (ACell *)[nib objectAtIndex:0];
}
//Custom cell with whatever
//[cell.customLabelA setText:#"myText"]
}
//We use CellType2 xib for other rows
else{
static NSString *CellIdentifier = #"BCell";
cell =(BCell*) [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if(cell==nil){
NSArray *nib= [[NSBundle mainBundle] loadNibNamed:#"BCell" owner:self options:nil];
cell = (BCell *)[nib objectAtIndex:0];
}
//Custom cell with whatever
//[cell.customLabelB setText:#"myText"]
}
return cell;
}
First you create some custom UITableViewCell classes (.h and .m), as many as you have xib files:
So you could have CellType1 and CellType2 for example.
CellType1.h would look something like
#import <UIKit/UIKit.h>
#interface CellType1 : UITableViewCell
#property(nonatomic,strong) IBOutlet UILabel *customLabel;
#end
Then you create the xib files, you can use default view type, but then, just remove the view that is automatically created, replace that by a UITableViewCell, and change the class to CellType1. Do the same for CellType2.
Then in your tableViewController, write cellForRow like this:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell=nil;
//We use CellType1 xib for certain rows
if(indexPath.row==<whatever you want>){
static NSString *CellIdentifier = #"CellType1";
cell =(CellType1*) [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if(cell==nil){
NSArray *nib= [[NSBundle mainBundle] loadNibNamed:#"CellType1" owner:self options:nil];
cell = (CellType1 *)[nib objectAtIndex:0];
}
//Custom cell with whatever
[cell.customLabel setText:#"myText"]
}
//We use CellType2 xib for other rows
else{
static NSString *CellIdentifier = #"CellType2";
cell =(CellType2*) [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if(cell==nil){
NSArray *nib= [[NSBundle mainBundle] loadNibNamed:#"CellType2" owner:self options:nil];
cell = (CellType2 *)[nib objectAtIndex:0];
}
//Custom cell with whatever
[cell.customLabel setText:#"myText"]
}
return cell;
}
If you're not already familiar with loading a custom cell from a xib, check out the documentation here. To extend this to multiple custom xibs, you can create each table cell in a separate xib, give it a unique cell identifier, set the table view controller as the file's owner, and connect each cell to the custom cell outlet you define (in the docs, they use tvCell as this outlet). Then in your -tableView:cellForRowAtIndexPath: method, you can load the correct xib (or dequeue the correct reuseable cell) by checking which row you're providing a cell for. For example:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *MyIdentifier1 = #"MyIdentifier1";
static NSString *MyIdentifier2 = #"MyIdentifier2";
static NSString *MyIdentifier3 = #"MyIdentifier3";
static NSString *MyIdentifier4 = #"MyIdentifier4";
NSUInteger row = indexPath.row
UITableViewCell *cell = nil;
if (row == 0) {
cell = [tableView dequeueReusableCellWithIdentifier:MyIdentifer1];
if (nil == cell) {
[[NSBundle mainBundle] loadNibNamed:#"MyTableCell1" owner:self options:nil];
cell = self.tvCell;
self.tvCell = nil;
}
}
else if (row == 1) {
cell = [tableView dequeueReusableCellWithIdentifier:MyIdentifer2];
if (nil == cell) {
[[NSBundle mainBundle] loadNibNamed:#"MyTableCell2" owner:self options:nil];
cell = self.tvCell;
self.tvCell = nil;
}
}
else if (row == 2) {
cell = [tableView dequeueReusableCellWithIdentifier:MyIdentifer3];
if (nil == cell) {
[[NSBundle mainBundle] loadNibNamed:#"MyTableCell3" owner:self options:nil];
cell = self.tvCell;
self.tvCell = nil;
}
}
else if (row == 4) {
cell = [tableView dequeueReusableCellWithIdentifier:MyIdentifer4];
if (nil == cell) {
[[NSBundle mainBundle] loadNibNamed:#"MyTableCell4" owner:self options:nil];
cell = self.tvCell;
self.tvCell = nil;
}
}
// etc.
// Do any other custom set up for your cell
return cell;
}
In CustomCell.m I define init method where I want to load cell from the IB:
- (id)init {
self = [super init];
if (self) {
NSArray *nib =[[NSBundle mainBundle] loadNibNamed:#"CustomCell" owner:self options:nil];
self = [nib objectAtIndex:0];
}
return self;
}
In the MyTableViewController.m in the method cellForRowAtIndexPath I initialize my custom cell
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
cell=[[CustomCell alloc]init];
return cell;
}
Everything works as I expected but when I did Product -> Analyse I get
Returning 'self' while it is not set to the result of '[(super or self) init...]'
What am I doing wrong?
You are overwriting self (returned from super init) with the object returned from your array. If you want to load a custom cell from a nib, do it in your cellForRowAtIndexPath method, or create a convenience class method on your custom cell that loads from the nib:
In your cellForRowAtIndexPath:
cell = [CustomCell cell];
In your cell's implementation:
+(CustomCell*)cell
{
NSArray *nib =[[NSBundle mainBundle] loadNibNamed:#"CustomCell" owner:self options:nil];
return [nib objectAtIndex:0];
}
EDIT - changed method name since new* indicates that a retained object will be returned.
Keep your init method as below, and do the linking in the Interface Builder
- (id)init {
self = [super init];
if (self) {
}
return self;
}
And
- (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;
}
}
}
}
What I am doing is
-(id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self)
{
// Initialization code.
//
UITableViewCell *view = [[[NSBundle mainBundle] loadNibNamed:#"SmallCellView" owner:self options:nil] lastObject];
self.backgroundView = view;
}
return self;
}
then in the main class
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
SmallCellView *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[SmallCellView alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
return cell;
}
For me this is working fine and in Product -> Analyse is not giving any warning or error
I met the same problem, I have fixed it by removing the code that like
NSArray *nib =[[NSBundle mainBundle] loadNibNamed:#"CustomCell" owner:self options:nil];
return [nib objectAtIndex:0];
from the CustomView's definition init Method.
Put these code the at the place where you create the Custom.
Is there a way to use multiple uitableviewcell classes with nib files in the tableViewController?
There's this great tutorial video for how to create custom cell classes to be used in a tableViewController at the cellForRowAtIndexPath function that I'm pasting here in case anyone wants to see.
In this example though, they are only using one type of reusable cell class. This is from my own project but it's essentially what the tutorial presents. "videoCellEntry" is a custom cell that I have created with nib file videoEntryCell.xib, "videoEntry" is the class for each cell that I am configuring, and "videos" is an array of videoEntry.
I'm assuming to use multiple nib files, I can put some conditions to choose which nib file I want and then call a different loadNibNamed: portion like so:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"videoCellId";
videoEntryCell *cell =
(videoEntryCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
if(<condition 1>) {
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"videoEntryCell" owner:self options:nil];
}
if(<condition 2>) {
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"videoEntryCell2" owner:self options:nil];
}
cell = (videoEntryCell *)[nib objectAtIndex:0];
}
// Configure the cell.
videoEntry *vid = [videos objectAtIndex:indexPath.row];
[cell configureForVideoEntry:vid];
return cell;
}
But can the tableViewController handle multiple cell nib files? Or is there a better way? And wouldn't each cell require a different CellIdentifier depending on its nib file?
Yes, you can use multiple Nib-Files and multiple CellIdentifiers in the TableViewController. Just put your condition before the CellIdentifier. That's the way I've done it.
Some example inside the - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath method:
First define the variable cell:
UITableViewCell *cell;
Now the if-Block:
if(<condition 1>) {
static NSString *CellIdentifier = #"VideoCell1";
cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:#"videoEntryCell" owner:nil options:nil];
for (id currentObject in topLevelObjects){
if([currentObject isKindOfClass:[UITableViewCell class]]){
cell = (UITableViewCell *) currentObject;
break;
}
}
}
// customize your cell here
}
if(<condition 2>) {
static NSString *CellIdentifier = #"VideoCell2";
cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:#"videoEntryCell2" owner:nil options:nil];
for (id currentObject in topLevelObjects){
if([currentObject isKindOfClass:[UITableViewCell class]]){
cell = (UITableViewCell *) currentObject;
break;
}
}
}
// customize your cell here
}
and finally:
return cell;
You can repeat the if-Block as often as you want. It's only important that you return a cell, which is not nil.