I would like to know where to enter custom code to change the value of a Label property for a UITableViewCell.
I am not sure how this is loaded, as I have put an NSLog in the ViewDidLoad and (id)initWithStyle instance methods but neither write to the log.
I have setup a NIB and custom class all correctly linked, and the Label is linked as a property and no longer causes an error. But I am unable to setText.
This is how the custom cell is called:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
LeftMenuTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
NSArray* views = [[NSBundle mainBundle] loadNibNamed:#"LeftMenuTableViewCell" owner:nil options:nil];
for (UIView *view in views) {
if([view isKindOfClass:[UITableViewCell class]])
{
cell = (LeftMenuTableViewCell*)view;
}
}
}
return cell;
}
This is the code in the IMP file for the LeftMenuViewCell class.
-(void)viewDidLoad {
displayName.text = [self.user objectForKey:#"displayName"];
I can set the displayName to a string and this does not change either. If I add an NSLog to the viewDidLoad for the custom cell class it is not shown, like it is not loaded, but the cell is loaded...?
Without code specifics, I can only give a vague'ish answer.
Your custom cell will need to subclass UITableViewCell, and you need to provide your table with this custom subclass when the data source method tableView:cellForRowAtIndexPath:.
I'd suggest reading up on how cells are added/used with UITableViews:
http://developer.apple.com/library/ios/#documentation/UserExperience/Conceptual/TableView_iPhone/TableViewCells/TableViewCells.html#//apple_ref/doc/uid/TP40007451-CH7-SW1
Let's say that you have custom UITableViewCell with UILabel called testLabel. If your NIB and custom class are properly linked than you can use following code:
MyTableViewCell.h
#interface MyTableViewCell : UITableViewCell
#property (nonatomic, assign) IBOutlet UILabel *testLabel;
#end
cellForRowAtIndexPath in your UITableViewController or UIViewController:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"MyTableViewCellId";
MyTableViewCell *cell = (MyTableViewCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:#"MyTableViewCell" owner:self options:nil];
cell = [topLevelObjects objectAtIndex:0];
}
[cell.testLabel.text = [_dataSource objectAtIndex:[indexPath row]]];
return cell;
}
Hope it helps :)
For example
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
RouteCell *routeCell = [self.tableView dequeueReusableCellWithIdentifier:routeIdentifier];
if (routeCell == nil) {
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"RouteCell" owner:nil options:nil];
routeCell = [nib objectAtIndex:0];
}
routeCell.travelTime.text = #"Here you are setting text to your label";
return routeCell;
Related
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.
I've a custom UITableViewCell subclass and I've read that this is supposed to be the correct way of loading custom cells for iOS 5:
- (UITableViewCell *)tableView:(UITableView *)tv cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
CustomCell *cell = [tv dequeueReusableCellWithIdentifier:#"customCell"];
if (cell == nil) {
cell = [[CustomCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"customCell"];
// Configure cell
cell.nameLabel.text = self.customClass.name;
}
return cell;
}
But the label text is not shown when I run the app. However, I also tried this way:
- (UITableViewCell *)tableView:(UITableView *)tv cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tv dequeueReusableCellWithIdentifier:#"customCell"];
if (cell == nil) {
NSArray* views = [[NSBundle mainBundle] loadNibNamed:#"CustomCell" owner:nil options:nil];
for (UIView *view in views) {
if([view isKindOfClass:[UITableViewCell class]])
{
cell = (CustomCell *)view;
}
}
// Configure cell
((CustomCell *)cell).nameLabel.text = self.customClass.name;
}
return cell;
}
This way the label is displayed, but any reuseIdentifier is set in loadNibName: method. What the best way of loading custom cells should be? I need to support iOS 5+. Could the first approach not be working because I'd to configure cell's labels and styles in initWithStyle: method and not in the table view's method?
Thanks!
The error in your code is that cell.nameLabel.text is only set in the if (cell == nil) { ... } case and not generally.
The easiest ways to load custom cells are
Use registerNib:forCellReuseIdentifier: if the cell is defined in a nib file, or
use registerClass:forCellReuseIdentifier: if the cell is created programmatically, or
use a Storyboard and define "CustomCell" as "Prototype Cell" for the table view.
For example (in viewDidLoad):
[self.tableView registerNib:[UINib nibWithNibName:#"CustomCell" bundle:nil] forCellReuseIdentifier:#"customCell"];
Then dequeueReusableCellWithIdentifier
will always return a cell, so that cellForRowAtIndexPath simplifies to
- (UITableViewCell *)tableView:(UITableView *)tv cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
CustomCell *cell = [tv dequeueReusableCellWithIdentifier:#"customCell"];
cell.nameLabel.text = self.customClass.name;
return cell;
}
Just use this code and try.
static NSString *cellIdentifier=#"cell";
YourCustomCell *cell = (YourCustomCell *) [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell == nil)
{
NSString *customeCellName = [NSString stringWithFormat:#"%#",[YourCustomCell class]];
NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:customeCellName owner:self options:nil];
for (id currentObject in topLevelObjects)
{
if ([currentObject isKindOfClass:[UITableViewCell class]])
{
cell = (YourCustomCell *) currentObject;
break;
}
}
}
cell.nameLabel.text = self.customClass.name; // Make sure self.customclass.name have value.
return cell;
Use this code (NewCustomCell is your Custom UITableViewCell class name)...
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
NewCustomCell *cell = (NewCustomCell*)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
NSArray *nib=[[NSBundle mainBundle]loadNibNamed:#"NewCustomCell" owner:self options:nil];
cell=[nib objectAtIndex:0];
}
return cell;
}
Happy coding... :)
I have a custom UITableViewCell that's loaded from a nib. I can pull this into my app with a reuseIdentifier by performing the following steps:
1) Set the reuse identifier in the Nib as "CustomCellIndentifier"
2) Register the nib:
[[self tableView] registerNib:[UINib nibWithNibName:#"CustomCell" bundle:nil] forCellReuseIdentifier:#"CustomCellIndentifier"];
3) Return the cell in tableview:cellForRowAtIndexPath
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
CustomCell *cell = [tableView dequeueReusableCellWithIdentifier:#"CustomCellIndentifier"];
return cell;
}
My question is, how can I return a cell WITHOUT a reuse identifier? I have a small table and I don't want the cell to be reused (it messes up some subviews I have in the cell if I scroll).
I've tried a combination of setting the above 3 reuse identifiers to nil and they all generate errors.
I've also tried this below, but the cell contents reset if I scroll past the cell and I get an error message "no index path for table cell being reused":
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
CustomCell *cell = [tableView dequeueReusableCellWithIdentifier:nil];
if (cell == nil) {
NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:#"CustomCell" owner:self options:nil];
cell = [topLevelObjects objectAtIndex:0];
}
return cell;
}
I think this is not a good way, but as per your requirement Use this:
Write the init method in your CustomCell class
- (id)init
NSArray *nibObjects = [[NSBundle mainBundle] loadNibNamed:#"QuestionOptionCell" owner:self options:nil];
CustomCell *theEditView = [nibObjects objectAtIndex:0];
self = theEditView;
theEditView = nil;
return self
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
CustomCell *cell = [[CustomCell alloc] init];
if (cell == nil) {
NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:#"CustomCell" owner:self options:nil];
cell = [topLevelObjects objectAtIndex:0];
}
return cell;
}
I really can't understand why i get a "EXC_BAD_ACCESS" in the line where I assign NSArray *topLevelObjects. It's crazy because I use exactly the same code and the same BlogCell in another tabliView, and there it's working perfectly!
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
int r = indexPath.row;
static NSString *CellIdentifier = #"Blog";
BlogCell *cell = (BlogCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:#"BlogCell" owner:self options:nil];
cell = [topLevelObjects objectAtIndex:0];
}
return cell;
}
Make sure all the outlets you specify in BlogCell to FilesOwner have corresponding IBOutlets in this class.
When I run my ios app, only the first cell displays in the TableView, then when clicked the second cell displays. I would like them both to display at the same time, but I cannot figure out this behavior.
Here is the code for my view did load
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"ProductCellId";
ProductTableCell *cell =
(ProductTableCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
[[NSBundle mainBundle] loadNibNamed:#"ProductTableCell" owner:self options:nil];
cell = self.productCell;
}
Product *product = [products objectAtIndex:indexPath.row];
[cell configureForProduct:product];
return cell;
}
Any help would be much appreciated!
Since you are loading your cell from Interface builder try this:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath: (NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"ProductTableCell"];
if (cell == nil) {
// Load the top-level objects from the custom cell XIB.
NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:#"ProductTableCell" 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];
}
Product *product = [products objectAtIndex:indexPath.row];
[cell configureForProduct:product];
return cell;
}
Change this:
static NSString *CellIdentifier = #"ProductCellId";
to:
static NSString *CellIdentifier = #"ProductTableCell";
You can find additional information for what you are trying to do in this question: Load cells from XIB files