have a UITableViewCell, to which I add a label on it with tag 1000.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"ChecklistItem"];
UILabel *label = (UILabel *) [cell viewWithTag:1000];
if (cell == nil)
{
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
then
UILabel *labelName = (UILabel *)[cell viewWithTag:1000]
labelName.text = #"test".
When I run, the cell is empty. Any advice?
The problem could also be that you aren't using a unique tag number. Meaning that something in your view controller scene could possibly have the same tag number that you have defined on another object.
For example, for me, I had a UITableViewCell which had a tag # of 0 and a UILabel with a tag # of 0 and another UILabel with a tag # of 1. This caused problems and made it to where tag #1 wouldn't display at all. I could see the text when I clicked on the row -- but the data wouldn't show when the row wasn't clicked on.
When I changed the tag numbers of both UILabels, it fixed the issue.
You should check if [tableView dequeueReusableCellWithIdentifier:#"ChecklistItem"] and [cell viewWithTag:5000] are returning something other than nil.
If they are, be sure to do it in this order:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
//Try to reuse the cell
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"ChecklistItem"];
//If you can't reuse, instantiate the cell
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"ChecklistItem"];
}
//Now that you have your cell, find the label
UILabel *labelName = (UILabel *)[cell viewWithTag:5000];
//Check if the label exists just in case
if (labelName) {
//And set the text
[labelName setText:#"test"];
}
}
The issue already solved, my application was working very fine on iPhone, so I decide to make it universal. I copy all view controller to iPad storyboard. And I start doing some change on iPad storyboard.
Whatever I add/delete on iPad storyboard, didn't make any change as the main interface was iphone and the reason was that I didn't change the main interface for iPad, so while running on iPad, I was using the storyboard of iPhone.
Related
I'm struggling with this basic thing for more than a day and it drives me crazy! Funny thing is, I have very similar thing on other screen and it works just fine! I have done this a thousand times, but never experienced something so odd. Maybe is this behavior in iOS 8 only?
On my very simple Prototype cell I have two labels with tags 102 and 103. But when I want to set text to them, they are always nil.
I have double checked that identifier is correct and that tag is the same as in Storyboard.
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString * identifier = #"secondReusableIdentifier";
UITableViewCell *cell = (UITableViewCell *)[tableView dequeueReusableCellWithIdentifier:identifier];
if (cell == nil){
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier];
}
for (UIView *subview in [cell subviews]) {
NSLog(#"subview: %lu", subview.tag); // prints 0
}
UILabel * label1 = (UILabel *)[cell viewWithTag:102]; // returns nil
UILabel * label2 = (UILabel *)[cell viewWithTag:103]; // returns nil
if (self.items.count) {
MyObject *obj = [self.items objectAtIndex:indexPath.row];
label1.text = obj.someProperty;
fuelPrice2.text = obj.someOtherProperty;
}
}
return cell;
Any suggestions would be appreciated.
In your code you are creating a new cell, that it's not the same than you have in Storyboard.
Change this: This is the old way, or the way you use when the cell is by code or nib, and you don't use storyboard. This code means.
NSString * identifier = #"secondReusableIdentifier";
// If I have available a cell with this identifier: secondReusableIdentifier, let's go to use it.
UITableViewCell *cell = (UITableViewCell *)[tableView dequeueReusableCellWithIdentifier:identifier];
if (cell == nil){
// If not, we create a new cell with this identifier. This methods is previous to storyboard, and this methods create a new cell, but does´t look in Storyboard if this identifier exist, or something like that.
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier];
}
To this, in other hand when Apple launched storyboard the framework grow with this methods, that work in this way: If there is a cell free use it, if not it look in Storyboard for a cell with this identifier and create a new cell with this info. (You can use this methods also by code and with nib file, but you must register the class before...).
// Be sure than: "secondReusableIdentifier", it's its identifier in storyboard
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"secondReusableIdentifier" forIndexPath:indexPath];
Replacing this:
NSString * identifier = #"secondReusableIdentifier";
UITableViewCell *cell = (UITableViewCell *)[tableView dequeueReusableCellWithIdentifier:identifier];
if (cell == nil){
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier];
}
BY
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"secondReusableIdentifier" forIndexPath:indexPath];
for creating a cell will solve your problem because, it always returns a cell. It either re uses existing cells or creates a new one and returns if there are no cells.
The most important difference is that the forIndexPath: version crashes if you didn't register a class or nib for the identifier. The older (non-forIndexPath:) version returns nil in that case.
You must register a class or nib for using this. But if you create your table view and your cell prototypes in a storyboard, the storyboard loader takes care of registering the cell prototypes that you defined in the storyboard.
Hope this helps.. :)
If
for (UIView *subview in [cell subviews]) {
NSLog(#"subview: %lu", subview.tag); // prints 0
}
prints 0, why do you do this??
UILabel * label1 = (UILabel *)[cell viewWithTag:102];
UILabel * label2 = (UILabel *)[cell viewWithTag:103];
So, if you created a custom cell with IB, you have to create a custom class and use it instead of a simple UITableViewCell
I have following code :
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSString *tableId = #"details";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:tableId];
if(cell == nil)
{
cell = [ [UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:tableId];
}
[((UIImageView *)[cell viewWithTag:101]) setImage:[UIImage imageNamed:[homeInvCaptureViewModel.productArray objectAtIndex:indexPath.row]]];
return cell;
}
I have a table view in storyboard. Yet, my data is not shown up in my table rows. (i.e., imageview).
I just try your code, and it's working for me, so I see some explanations for your bug:
Did you set 101 for your ImageView's tag in your storyboard?
Did you set details as cell's identifier is in your storyboard?
Are you sure your image's name from your productArray exists in your project's images?
You should set an image at your ImageView in your storyboard to identify,
I believe this question is my exact problem, but I was not able to fix the issue looking at the accepted answer.
UISearchBar: FilterContentForSearchText not working on a UITableView (results not shown on table)
I have a UITableViewController that allows searching. It was working perfectly via the default UITableViewCellStyle, then I decided to implement my own custom layout for the cells. I did not subclass UITableViewCell, but instead added two UILabels to the cell via Interface Builder and set up Auto Layout. I assigned them unique tags so that I can reference those labels in cellForRowAtIndexPath:. It works great - everything appears as expected, until you search. The search does work and it displays the sections and rows, but the labels on the rows have no text so the cell appears completely blank.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"List View Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
UILabel *leftLabel = (UILabel *)[cell viewWithTag:100];
UILabel *rightLabel = (UILabel *)[cell viewWithTag:101];
if (tableView == self.searchDisplayController.searchResultsTableView) {
leftLabel.text = ...;
rightLabel.text = ...;
}
else {
leftLabel.text = ...;
rightLabel.text = ...;
}
return cell;
}
I do know why the labels are blank. When you search, dequeueReusableCellWithIdentifier: returns nil so it inits a new cell with the reuse identifier, but that cell does not have a viewWithTag: and this results in left and right label becoming nil. So it obviously cannot add text to nil.
The answer provided in the link stated you should create the label in the if (!cell) statement and then call [cell.contentView addSubview:left{right}Label];. I did that, and then moved my label configuration code into that if statement as well. But when I do that, the main table's rows only has the default values of my left and right labels from Storyboard - it doesn't set the text of the labels. This is because dequeueReusableCellWithIdentifier: doesn't return nil and instead creates a new cell, so it doesn't ever set the text because that's in the if (!cell) statement.
I could not figure out how to take care of both situations: when cell is nil and when it is not. What do I need to do to fix this?
More comments: I've never used xib files before and I'd prefer to keep it that way. :) I wouldn't mind subclassing UITableViewCell if that's a solution. Of course, I would like to implement this the "proper" way - only create a cell when one is needed etc.
I think the easiest way to do this is to make your cell in a xib file if you want to use the same cell type for both the main table and the search results table. You can make a subclass if you want (you only need to put in IBOutlets to your two labels in the .h file), or do it the same way you already did using tags. In viewDidLoad of the table view controller, register the nib for both tables,
[self.searchDisplayController.searchResultsTableView registerNib:[UINib nibWithNibName:#"CommonCell" bundle:nil] forCellReuseIdentifier:#"CommonCell"];
[self.tableView registerNib:[UINib nibWithNibName:#"CommonCell" bundle:nil] forCellReuseIdentifier:#"CommonCell"];
Then in cellForRowAtIndexPath:, you only need to dequeue the cell with that same identifier, and populate the labels. There's no need to check for cell equals nil, because it never will be.
I modified one of my apps to show how you can implement cellForRowAtIndexPath. I subclassed the cell (CommonCell is the class), only adding IBOutlets to the leftLabel, and rightLabel,
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
CommonCell *cell = [tableView dequeueReusableCellWithIdentifier:#"CommonCell" forIndexPath:indexPath];
cell.leftLabel.text = ([tableView isEqual:self.tableView])? self.theData[indexPath.row] : self.filteredData[indexPath.row];
cell.rightLabel.text = ([tableView isEqual:self.tableView])? self.theData[indexPath.row] : self.filteredData[indexPath.row];
return cell;
}
This is conceptually wrong: you are instantiate a NEW CELL from code that is not the cell from interface builder. If you want use that on interface builder you need to register the nib for your tableView, and associate it to an identifier (se the same identifier also in the cell on interface builder):
[self.searchDisplayController.searchResultsTableView registerNib:[UINib nibWithNibName:#"NameNib" bundle:[NSBundle mainBundle]] forCellReuseIdentifier:#"Identifier"];
But the question is: why? The best thing to do is create a subclass and add your labels. It is really simple:
1) Create a new file CustomSearchCell object that extends UITableViewCell:
CustomSearchCell.h
#import <UIKit/UIKit.h>
#interface CustomSearchCell : UITableViewCell
#property (strong, nonatomic) UILabel *leftLabel;
#property (strong, nonatomic) UILabel *rightLabel;
#end
CustomSearchCell.m
#import "CustomSearchCell.h"
#implementation CustomSearchCell
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
// Initialization code
_leftLabel = [[UILabel alloc] initWithFrame:CGRectMake(100, 10, 200, 45)];
[_leftLabel setFont:[UIFont systemFontOfSize:20.0]];
[_leftLabel setTextColor:[UIColor blackColor]];
_rightLabel = [[UILabel alloc] initWithFrame:CGRectMake(100, 45, 200, 25)];
[_rightLabel setFont:[UIFont systemFontOfSize:15.0]];
[_rightLabel setTextColor:[UIColor grayColor]];
[self.contentView addSubview: _leftLabel];
[self.contentView addSubview: _rightLabel];
}
return self;
}
#end
2) In your view controller:
#import "CustomSearchCell.h"
and:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"ListCellIdentifier";
CustomSearchCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (!cell) {
cell = [[CustomSearchCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
if (tableView == self.searchDisplayController.searchResultsTableView) {
cell.leftLabel = ...;
cell.rightLabel = ...;
}
else {
cell.leftLabel = ...;
cell.rightLabel = ...;
}
return cell;
}
I have added a UILabel as the content view of my tableview. The text in the UILabel is overlapping upon scrolling. Below is the code.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
[self.chatTableView registerClass:[UITableViewCell class] forCellReuseIdentifier:#"Group"];
static NSString *CellIdentifier = #"Group";
UITableViewCell *cell = [self.chatTableView dequeueReusableCellWithIdentifier:CellIdentifier
forIndexPath:indexPath];
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle
reuseIdentifier:CellIdentifier];
}
cell.textLabel.text = self.latestTrimText;
UILabel *cellLabel = [[UILabel alloc]init];
cellLabel.text = self.dateOfLatestTrim;
cellLabel.frame = CGRectMake(15, 0, 150, 30);
[cell.contentView addSubview:cellLabel];
return cell;
}
I can fix this by changing to UITableViewCell *cell = [self.chatTableView dequeueReusableCellWithIdentifier:nil];
But then, the scrolling of the tableview won't be smooth. Is there another way to fix the issue?
The tableview cells are recycled and reused potentially an infinite amount of times. This is what the reuse identifier stands for.
Take care not to add any subview outside the if (cell==nil) block. Now you are just adding again and again a new label to the same cell instance. This is why your texts overlaps each other.
I would recommend you to read the documentation on how the cells are recycled and reused.
Your fix is not correct because by passing a nil reuse id, you are just preventing the recycling process to play. You create a new instance for each row of your tableview. This is why you have performance issues then.
I am trying to add 2 labels in my table view cell.
when in portrait mode the both labels overlap each other and in landscape mode it works fine.
I have also used auto-layout . Where i have to make changes to achieve the target.
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *MyIdentifier = #"ProductTableViewCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:MyIdentifier];
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:MyIdentifier];
}
UILabel * productName= (UILabel *)[cell viewWithTag:101];
//productName.text=[[productDetails objectAtIndex:indexPath.row]product_Name];
// similar code for another label also
productName.lineBreakMode= NSLineBreakByWordWrapping;
productName.numberOfLines=0;
productName.text= #"asdfasdfsdzxcvzasdfaxv";
[productName sizeToFit];
return cell;
}
Link for Issue for better description : http://f.talk.to/3afcd0c13764064184c01cc4
Thanks in advance :)