I am trying to use two differently formatted UITableViewCells depending on if it's an iPad or iPhone. Both the cells show the same information, but the iPad cell has half the height and double the width. So the information is shown on one line vs two lines.
In my cellforRowatIndexPath,
I am putting the code:
HistoryCell *cell;
if (self.isiPad) {
cell = [self.tableView dequeueReusableCellWithIdentifier:#"historyiPadCellType" forIndexPath:indexPath];
}
else{
cell = [self.tableView dequeueReusableCellWithIdentifier:#"historyCellType" forIndexPath:indexPath];
}
However it seems like if I have 2 UItableViewCells in the same XIB, it will give me an error:
invalid nib registered for identifier (historyCellType) - nib must contain exactly one top level object which must be a UITableViewCell instance'
Is there anyway to fix this?
Thanks!
The best way to use differetnt cell for iPad and iPhone it is using 2 nibs:
HistoryCell~iphone.xib and HistoryCell~ipad.xib
And you must register you nib:
[self.tableView registerNib:[UINib nibWithNibName:#"HistoryCell" bundle:nil] forCellReuseIdentifier:#"historyCellType"];
System automatically loads xib depending on current device.
Related
I have a custom UITableViewCell class that I want to use to create custom table cells. I created the custom table cell's xib as well as its header and implementation files, all called RTRepairOrderTableCell.m/.h/.xib.
My issue is that even though I set the reuse identifier of the table cell to RTRepairOrderTableCell inside of the .xib file and registered the xib inside of my table view controller, I am still getting assertion errors when it tries to dequeue or create a new cell for use.
Inside of my view (table) controller I have the following:
- (void)viewDidLoad
{
[super viewDidLoad];
//Load the nib file
UINib *nib = [UINib nibWithNibName:#"RTRepairOrderTableCell"
bundle:nil];
// Register this Nib, which contains the cell
[self.tableView registerNib:nib
forCellReuseIdentifier:#"RTRepairOrderTableCell"];
}
There are no errors here and it finishes viewDidLoad just fine.
Inside of my cellForRowAtIndexPath I have the following:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
RTRepairOrderTableCell *cell = [tableView dequeueReusableCellWithIdentifier:#"RTRepairOrderTableCell" forIndexPath:indexPath];
return cell;
}
According to every tutorial I've seen, this should work so long as I have the reuse identifier set properly inside the xib file and I register that xib inside of viewDidLoad in the view controller class that will display the table cells, so I am at a loss as to why I am getting
*** Assertion failure in -[UITableView _dequeueReusableViewOfType:withIdentifier:], /SourceCache/UIKit/UIKit-2935.138/UITableView.m:5413
Turns out I had a few orphaned UIImage objects inside the nib file but outside of the UITableViewCell area, so it was throwing errors saying that the UITableViewCell needed to be the topmost view.
I faced this and it was driving me crazy. But it was my fault. I had set identifier #"Abc" in Nib file and I was registering the same nib file with some other identifie #"Xyz". Removed the identifier from nib, left that part blank and it worked like a champ. :)
This might be a rare case, but due to some sloppy copy pasta two different UITableViewCell custom classes used in my table had the exact same Identifier specified in the Xib.
Switching one of these cells to have a different Identifier in the Attributes Inspector fixed my Assertion failures.
Check if in your .xib there are no UI component outside main layout:
Label is not accepted
In this example, Label is not accepted and cause the exception
I've got an UITableViewCell with a UITextField in it. When I click the UITextField I want to make sure the entire cell is visible in the tableView. I did this in textfieldDidBeginEditing, like so:
- (void) textFieldDidBeginEditing:(id)textField {
TTTableViewCell *cell = (TTTableViewCell *)[self.tableView cellForRowAtIndexPath:objc_getAssociatedObject(textField, kIndexPathId)];
[self.tableView setContentOffset:CGPointMake(cell.frame.origin.x, cell.frame.origin.y - self.tableView.sectionHeaderHeight) animated:YES];
}
This works perfectly when the user goes down the list. Expect when to user taps a cell which is partial visible on the top it doesn't reveal the entire cell just moves a bit.
Does someone know a solution to this problem?
There are UITableView methods to solve exactly this. You can use scrollToRowAtIndexPath:atScrollPosition:animated: to ask the table view to bring a cell to the top by passing UITableViewScrollPositionTop.
(You might first want to check if it's already visible to ensure it doesn't scroll unnecessarily.)
Im transferring my project from xibs to using a storyboard. I just added the Settings page, which i made from a UIViewController to a UITableViewController. The table view cells are added using the static method in the storyboard. The table has 5 sections, with 12 cells. I have no other code doing anything to the TableView, and in the storyboard scrolling is on. When running on my iPhone 5 the view wont scroll, all the cells are there, and i can pull and see the cells hidden, but when letting go it scrolls to the top still. Like when pulling up on a page in a UIWebView basically. Xcode gives no warnings, or errors, how can i fix this?
Edit: I found the 2 lines of code causing it not to scroll, But i still don't know how to fix it. The code gets the custom TextFieldTableCell and sets the text for it, because I'm using a storyboard, It doesn't call CellForRow,
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
TextFieldTableCell *cell = (TextFieldTableCell *)[SettingsTable cellForRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]];
cell.textField.text = [[NSUserDefaults standardUserDefaults] objectForKey:#"Homepage"];
}
The TableView is only disabled from scrolling if the 2 lines under [super viewWillAppear:animated]; are called in the method - (void)viewWillAppear:(BOOL)animated, but if i call the lines in - (void)viewDidAppear:(BOOL)animated it will still scroll, except it takes a second to show that text, which isn't something i want, should be auto-loaded when user see's the TableViewController, are there any workarounds? Any other methods called like viewWillLoad but shouldn't disable the table?
This seems like a simple thing but I'm stuck.
In my storyboard, I have a cell with text in it's label (using Static Cells). In didSelectRowAtIndexPath, I'm trying to access the cell's textLabel's text. Here's my code, with NSLogging:
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
if (cell.textLabel.text) {
NSLog(#"cell.textLabel.text = %#",cell.textLabel.text);
} else {
NSLog(#"!cell.textLabel.text");
}
NSLog(#"just for fun: cell.textLabel.text = %#", cell.textLabel.text);
The if statement always returns "!cell.textLabel.text" and the last NSLog is always (null) although the storyboard's cell has text in it.
Is cell.textLabel not correct? Should I be looking at another subview of UITableViewCell?
The default cell style of table cells in the Storyboard are of type 'Custom'. Which gives you a blank cell where you can add other types of controls to it.
If you dragged a label onto the cell and changed its text, then you are likely using a Custom style of UITableViewCell.
The property textLabel is only available on cells of types other than Custom, such as Basic, or Detailed.
Therefore you should first check out if these styles meet your requirements and use them instead.
If you really do require a Custom type of cell, you will need to make a subclass of UITableViewCell and create outlets to access your label.
I have my own table view cell which is defined in my storyboard. I have also defined a custom UITableViewCell class for this special cell. So when I want to create an Outlet for my custom prototype cell I get an error that the Outlet cant be created.
Since this is not possible I have to do some ugly workarounds and use the tags in IB to reference the individual labels and buttons later on in my code.
I don't really see why this is not possible and I wonder if working with tags and [myCell viewWithTag:] is the best possible way to go here?
Because the outlet is a one-to-one connection between your controller and a specific item within the view. In the case of a prototype cell, it is simply a description of a cell that can have an arbitrary number of different items (i.e. rows in your table view). How would the controller know which item you are referring to (e.g. row 5 or 500)? That is why you are receiving the error message.
Lucas provided one method to refer to your connection via tags which works perfectly well.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"CellIdentInIB"];
UIImageView *img = (UIImageView*) [cell.contentView viewWithTag:1];
//img.image = ...
//Access you prototype cell here to alter its style, example:
[[cell layer] setCornerRadius:10];
[cell setClipsToBounds:YES];
return cell;}
I assume you are using dynamic prototypes - in the attribute inspector of the tableview in the storyboard there is an option to select "static cells" or "dynamic prototypes". You can do what you are trying to do if you select "static cells" as there is only one cell in your tableview at run time for each cell in the storyboard. Using this approach you will only be able to use the cells you create in storyboard i.e. you will not be able to select the number of cells in your code.