How to reuse a UITableViewCell subclass in IB - iphone

I created a UITableViewCell subclass. In the HomeViewController class that currently uses it, I do this:
#interface: (for HomeViewController)
#property (nonatomic, assign) IBOutlet UITableViewCell *customCell;
#implementation:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CustomTableViewCellIdentifier = #"CustomTableViewCellIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CustomTableViewCellIdentifier];
if (cell == nil) {
UINib *cellNib = [UINib nibWithNibName:#"CustomTableViewCell" bundle:nil];
[cellNib instantiateWithOwner:self options:nil];
cell = self.customCell;
self.customCell = nil;
}
NSUInteger row = [indexPath row];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
return cell;
}
In the CustomTableViewCell.xib, my File's Owner is HomeViewController and I connect the outlet from File's Owner to the CustomTableViewCell. All of that works fine.
Now I want to have another subclass of UIViewController called DetailViewController to use this cell also. My File's Owner object is already used. I'm not super familiar with creating other objects in order to reuse this cell. Can someone explain what I need to do in this scenario? Thanks.

First, don't create a UINib object every time. Create it once and reuse it. It will run much faster.
Second, it looks like the only property of File's Owner that you're wiring up is customCell. If that's all you need, it would be simpler not to wire up a connection at all. Instead, make sure the cell is the first or only top-level object in the nib (by making it the first top-level object in the Objects section of the nib outline). Then you can access it like this:
+ (UINib *)myCellNib {
static UINib *nib;
static dispatch_once_t once;
dispatch_once(&once, ^{
nib = [UINib nibWithNibName:#"CustomTableViewCell" bundle:nil];
});
return nib;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CustomTableViewCellIdentifier = #"CustomTableViewCellIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CustomTableViewCellIdentifier];
if (cell == nil) {
NSArray *topLevelNibObjects = [self.class.myCellNib instantiateWithOwner:nil options:nil];
cell = [topLevelNibObjects objectAtIndex:0];
}
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
return cell;
}

Related

Custom UITableViewCell Not Using .xib (Most Likely Because of Flaw in init Method)

I subclassed the UITableViewCell in order to customize it, but I think I'm missing something because: 1) It's not working and 2) There are a couple of things I'm confused on. Along with customizing the look of the .xib file, I also changed the backgroundView, and that part is working fine. The part that I least understand/am most confused about is the init method, so I posted that here. If it turns out that is correct, please tell me so I can post more code that may be the cause.
This is the init method, which I customized. I'm sort of confused around the "style" idea and I think I'm just returning a normal UITableViewCell with a different backgroundView. I mean, there's nothing in there that refers to the .xib or does anything but change the .backgroundView from the self:
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier wait: (float) wait fadeOut: (float) fadeOut fadeIn: (float) fadeIn playFor: (float) playFor
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
CueLoadingView* lview = [[CueLoadingView alloc] initWithFrame:CGRectMake(0, 0, 320, 53)];
self.backgroundView = lview;
[self setWait:wait]; // in turn edits the lview through the backgrounView pointer
[self setFadeOut:fadeOut];
[self setFadeIn:fadeIn];
[self setPlayFor:playFor];
}
return self;
}
Other than the .xib and several setters and getters, this is the only real part of my code, that relates to retrieving a cell.
Additional Information:
1) This is my .xib, which is linked to the class.
2) This is the code that calls/creates the UITableView (the delegate/view controller):
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *simpleTableIdentifier = #"CueTableCell";
CueTableCell *cell = [tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil) {
cell = [[CueTableCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpleTableIdentifier wait:5.0 fadeOut:1.0 fadeIn:1.0 playFor:10.0];
[cell updateBarAt:15];
}
return cell;
}
The easiest way (available since iOS 5.0) to create a custom table view cell in a nib file is to use registerNib:forCellReuseIdentifier: in the table view controller. The big advantage is that dequeueReusableCellWithIdentifier: then automatically instantiates a cell from the nib file if necessary. You don't need the if (cell == nil) ... part anymore.
In viewDidLoad of the table view controller you add
[self.tableView registerNib:[UINib nibWithNibName:#"CueTableCell" bundle:nil] forCellReuseIdentifier:#"CueTableCell"];
and in cellForRowAtIndexPath you just do
CueTableCell *cell = [tableView dequeueReusableCellWithIdentifier:#"CueTableCell"];
// setup cell
return cell;
Cells loaded from a nib file are instantiated using initWithCoder, you can override that in your subclass if necessary. For modifications to the UI elements, you should override awakeFromNib (don't forget to call "super").
You have to load the cell from the .xib instead:
if ( cell == nil ) {
cell = [[NSBundle mainBundle] loadNibNamed:#"CellXIBName" owner:nil options:nil][0];
}
// set the cell's properties
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *simpleTableIdentifier = #"CueTableCell";
CueTableCell *cell = [tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil) {
NSArray *array = [[NSBundle mainBundle] loadNibNamed:#"CueTableCell XibName" owner:self options:nil];
// Grab a pointer to the first object (presumably the custom cell, as that's all the XIB should contain).
cell = [array objectAtIndex:0];
}
return cell;
}

setting UILabel.text of a custom UITableViewCell inside ViewController

I have a UITableView that I am populating with custom UITableViewCell in interface builder. I am having some issues accessing these custom tableviewcells properties and am hoping for some help.
In Interface Builder I am setting the custom tableviewcell's class to the current View controller (so I can assign all of the label objects to the correct labels in Interface Builder), So I have also set up the IBOutlet labels to the correct labels in Interface Builder However this error occurs when I try to pass the NSString from the array object variable (which is of type NSString) to the UIlabel's text.
Property 'cellDescription' not found on object of type 'UITableViewCell *'
Below is the code I have used to set up my tableview with the custom tableviewcell and then try to populate the cells UILabels with the correct text..
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (indexPath.section == 0) {
// Set cell height
[self tableView:tableView heightForRowAtIndexPath:indexPath];
// Configure the cell using custom cell
[[NSBundle mainBundle] loadNibNamed:#"AutomotiveSearchCell" owner:self options:nil];
cell = autoSearchCell;
//call dataArrayOfObject that has all of the values you have to apply to the custom tableviewcell
SearchResultItem* myObj = (SearchResultItem*)[dataArrayOfObjects objectAtIndex:indexPath.row];
cell.cellDescription.text = myObj.seriesDescription; // This is where I am receiving the error
NSLog(#"%#", myObj.seriesDescription); // This logs the correct value
//Disclosure Indicator
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
}
return cell;
}
you must typeCasting UITableViewCell To AutomotiveSearchCell
I think you code somewhere is strange(There is no declaration for autoSearchCell), but you must do the following.
cell = (AutomotiveSerachCell* )autoSearchCell;
The above code does not work, should following code.
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
convert to
AutomotiveSearchCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
If that does not work above, refer a following process.
make a CustomCell Class.
make a CustomCell xib.
linked label to CustomCell Class.
import header #import "AutomotiveSearchCell.h" and following code copy and paste.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
AutomotiveSearchCell *cell = nil;
if(!cell)
{
UINib *nib = [UINib nibWithNibName:#"AutomotiveSearchCell" bundle:nil];
NSArray *arr = [nib instantiateWithOwner:nil options:nil];
cell = [arr objectAtIndex:0];
cell.cellDescription.text = #"Test~!~!~!";
}
// Configure the cell...
return cell;
}

Loading a UITableViewCell subclass using a XIB file

I am having trouble getting my CustomTableViewCell, a subclass of UITableViewCell to appear in my table view.
I am using a xib to represent that cell, but I am assuming that the code for the data source delegate doesn't change. I made sure to set an identical reuse identifier inside the table view cell XIB.
I isolated the problem to the fact that the datasource method that returns the table cell isn't working correctly, here it is:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
CustomTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
DataObject *foo = [self.dataArray objectAtIndex:indexPath.row];
if (cell == nil)
{
cell = [[CustomTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
[[cell overview] setText:foo.overview];
[[cell price] setText:foo.price];
NSLog(#"cell initialized, description text is %#",cell.overview.text);
return cell;
}
Not sure why this isn't working, but that last log statement always prints a (null) at the end, and yes I did verify that the overview property of the data object has a valid string in it. Same thing for price.
1) Make your Custom cell class separate
2) XIB : File Owner class change to NSObject
3) XIB : UITableViewCell change to MyTableViewCell
4) Where you want to add inside table view code as
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *CellIdentifier = #"MyCell";
MyTableViewCell *cell = (MyTableViewCell*) [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
NSArray *arrayCellXib = [[NSBundle mainBundle] loadNibNamed:#"MyTableViewCell"
owner:self
options:nil];
if (indexPath.row == 0) {
// first table cell
cell = [arrayCellXib objectAtIndex:0]; // *
......
}else {
cell = [arrayCellXib objectAtIndex:1]; // *
}
...
}
return cell;
}
Object at index 0,1 ... are index for which order you make MyTableViewCell in xib, if you want to have more than one custom cell. means in a MyTableViewCell class u make unlimited custom cell and use according to requirement.
Normally, just make ONE custom cell in the XIB and do exactly this:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
int thisRow = indexPath.row;
NSString *exampleText = [yourData objectAtIndex:thisRow];
static NSString *CellID = #"cu5";
FancyCell *cell =
(FancyCell *)[tableView dequeueReusableCellWithIdentifier:CellID];
if (cell == nil)
{
NSArray *cellTeam =
[[NSBundle mainBundle] loadNibNamed:#"FancyCell"
owner:self options:nil];
cell = [cellTeam objectAtIndex:0];
}
[cell someFunction:exampleText];
[cell.someLabel setText:exampleText];
return cell;
}
Hoping may help u :)
In .h file, you write it.
IBOulet CustomTableViewCell *tableCell;
and connect to File's Owner in CustomTableViewCell's .xib file.
You modify this in (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
if (cell == nil)
{
[[NSBundle mainBundle] loadNibNamed:#"CustomTableViewCell" owner:self options:nil];
cell = tableCell;
}
I think it will be helpful to you.

Using dequeueReusableCellWithIdentifier with custom UITableViewCell

So I'm unsure how this dequeueReusableCellWithIdentifier works and if what I'm looking for is possible. I have a custom UITableViewCell with a BOOL showIcon. In the TableViewCell, if it's true, I show it, otherwise, I don't show this icon on my cell. In my cellForRowAtIndexPath, I grab the object in my array from my model, and set it for the UITableViewCell property.
This works at first on what is visible on my screen. Then as I scroll downwards on the table, it does not work and the values I should be seeing for the showIcon just don't show. And then when I scroll back to the top, the original icons that were there, are not there. Is the dequeueReusableCellWithIdentifier still what I want to be using in this case? Or am I doing something wrong with setting and showing data in it? Thanks a bunch.
CODE:
On my custom UITableViewCell, I have a
BOOL showIcon;
In my cellForRowAtIndexPath method, I use the UINib way of getting my custom UITableViewCell like this:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSUInteger row = [indexPath row];
static NSString *OrderTableViewCellIdentifier = #"OrderTableViewCellIdentifier";
OrderTableViewCell *cell = (OrderTableViewCell *)[tableView dequeueReusableCellWithIdentifier:OrderTableViewCellIdentifier];
if (cell == nil) {
UINib *cellNib = [UINib nibWithNibName:#"OrderTableViewCell" bundle:nil];
[cellNib instantiateWithOwner:self options:nil];
cell = self.TbvCell;
[cell.CheckmarkButton addTarget:self action:#selector(CheckmarkButtonPressed:) forControlEvents:UIControlEventTouchUpInside];
self.TbvCell = nil;
}
Order *order = [orderArray objectAtIndexPath:row];
cell.order = order;
}
Then in my TableViewCell, it's something like this:
#property (nonatomic, retain) Order *order;
#property (nonatomic, retain) UIImageView *icon;
overridden setter:
- (void)setOrder:(Order *)newOrder {
if (!order.showIcon) {
icon.hidden = YES;
}
}
Your code reuse your cell so you have to cover all the case in your setOrder method. Try with:
- (void)setOrder:(Order *)newOrder {
if (!order.showIcon) {
icon.hidden = YES;
}
else {
icon.hidden = NO;
}
}
Or simpler:
- (void)setOrder:(Order *)newOrder {
icon.hidden = !order.showIcon;
}
Yes, dequeueReusableCellWithIdentifier works well with any custom UITableViewCell subclasses. However, keep in mind that this method is for memory saving, so you'll have to do the following (even with not subclassed, normal UITableViewCells):
This method returns an already used UITableViewCell instance (or nil if the table view doesn't have enough cells yet). It means that the cell won't be "empty"; you'll need to clear and re-set all its properties. For example, you'll need to be able do decide from the cell's corresponding NSIndexPath whether its icon has to be displayad, and what icon image you'd like to use at all.
So edit your code like this:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSUInteger row = [indexPath row];
static NSString *OrderTableViewCellIdentifier = #"OrderTableViewCellIdentifier";
OrderTableViewCell *cell = (OrderTableViewCell *)[tableView dequeueReusableCellWithIdentifier:OrderTableViewCellIdentifier];
if (cell == nil) {
UINib *cellNib = [UINib nibWithNibName:#"OrderTableViewCell" bundle:nil];
[cellNib instantiateWithOwner:self options:nil];
cell = self.TbvCell;
[cell.CheckmarkButton addTarget:self action:#selector(CheckmarkButtonPressed:) forControlEvents:UIControlEventTouchUpInside];
self.TbvCell = nil;
}
// set your cell's properties to default values.
// e. g.: cell.showIcon = NO; and so on
Order *order = [orderArray objectAtIndexPath:row];
cell.order = order;
// then do a recustomization using the NSIndexPath's -row and -section properties
}
Hope this will help.

Custom Uicells in UIviewController giving error

I am trying to display a custom TableView on a UIViewController but am getting an error "UITableView dataSource must return a cell from tableView:cellForRowAtIndexPath:"
I had connected the TableView to datasource and delegate.
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Custom";
Custom *cell = (Custom *) [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
NSArray *topLevelObjects = [[NSBundle mainBundle]loadNibNamed:#"Custom" owner:self options:nil];
for (id currentObject in topLevelObjects)
{
if ([currentObject isKindOfClass:[Custom class]])
{
cell = (Custom *) currentObject;
break;
}
}
}
cell.textLabel.text =[arr objectAtIndex:indexPath.row];
please help
#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
Your code some wrong. below code refer plz. I've corrected.
Below code refer Befoe, Are you correctly make a customTableCell? below list check plz.
There are several ways to create about custtomTablecell.
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";
Custom *cell = (Custom *) [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (!cell)
{
UINib *nib = [UINib nibWithNibName:#"Custom" bundle:nil];
NSArray *arr = [nib instantiateWithOwner:nil options:nil];
cell = [arr objectAtIndex:0];
}
cell.textLabel.text =[arr objectAtIndex:indexPath.row];
}
It looks like you are not returning the created cell at the end of the method. Add 'return cell;' at the end and the error shall disappear.
Did you add the return statement? And is Custom a subclass of UITableViewCell?