UITableViewCell's textLabel's Font Change Not Visually Changed - ios

When I push a UIViewController onto my UINavigation controller like:
[(UINavigationController *)self.parentViewController pushViewController:[[[Fonts alloc] initWithNibName:#"Fonts" bundle:nil] autorelease] animated:YES];
Where Fonts.xib is a UIView with only UITableView controlled by a Fonts object that is a subclass of UIViewController and acts as the UITableView's dataSource and delegate.
In the Fonts object I create a UITableViewCell like:
- (UITableViewCell *) tableView: (UITableView *) tableView cellForRowAtIndexPath: (NSIndexPath *) indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier: #"BlahTableViewCell"];
if (!cell) {
cell = [[UITableViewCell alloc]
initWithStyle: UITableViewCellStyleDefault
reuseIdentifier: #"BlahTableViewCell"];
[cell autorelease]; // Delete for ARC
}
return cell;
}
And then I change the font of the cell here:
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
[cell.textLabel setFont:[(UIFont *)[self.listOfFonts objectAtIndex:indexPath.row] fontWithSize:cell.textLabel.font.pointSize]];
cell.textLabel.text = [(UIFont *)[self.listOfFonts objectAtIndex:indexPath.row] fontName];
}
listOfFonts is an NSArray of UIFont objects.
When the view appears it looks like UITableView without changed fonts
If I call reloadData on the UITableView or if I drag the UITableViewCells off screen with my finger and let them bounce back they are redrawn and the view the cells display with the labels having their fonts changed.
It seems like the issue is the UITableViewCells are being drawn too early. If I delay the drawing of them everything looks correct but I want the UITableView to be displaying correctly when the UINavigationController slides my view into place.
Any idea what I am doing wrong?
EDIT: I uploaded a simple and straightforward example of my issue to Dropbox. http://dl.dropbox.com/u/5535847/UITableViewIssue.zip

SOLVED IT!
Ok so I was having exactly the same issues as the original poster and this was the problem.
The line that's causing issues is:
[cell.textLabel setFont:[(UIFont *)[self.listOfFonts objectAtIndex:indexPath.row] fontWithSize:cell.textLabel.font.pointSize]];
Specifically, your issue is because you're trying to feed the cell's textLabel its own pointSize, but pointSize doesn't exist yet so strange bugs occur instead. For me, I noticed that a "transform" was failing due to a singular matrix being non-invertible. As soon as I hardcoded a standard value as my pointSize I saw all my labels draw with the proper font instantly. Note: this makes sense as to why a redraw worked, because then your textLabel does indeed have a pointSize.
In any case, you need to explicitly set your pointSize here, no using what the textLabel "already has" because it doesn't have anything until you're "reloading" a cell.

Set the label font inside -tableView:cellForRowAtIndexPath:.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *identifier = #"identifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier] autorelease];
// do it here if your font doesn't change ....
}
// otherwise here with your font ...
cell.textLabel.font = [UIFont boldSystemFontOfSize:12];
return cell;
}

I'm not sure that table cells are designed to be customisable in this way. The table cell may assume that you won't customise the font, and so not draw itself in a way that's compatible with what you are trying to do.
You'd be better off creating a custom table cell, or appending a UILabel as a subview to the table cell when you create it, and them setting the font of that label instead.
It may seem like overkill for such a small customisation, but it's flexible and it's guaranteed to work.

Related

UITableViewCell detailTextLabel disappears when scrolling

I'm using an array of strings where I set the detailTextLabel from. Initially all subtitles are set correctly but if I scroll the detailTextLabel disappears.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"personCell" forIndexPath:indexPath];
Person *person = [_persons objectAtIndex:indexPath.row];
cell.textLabel.text = person.name;
cell.detailTextLabel.text = person.phone;
// also tried setNeedsLayout but does not help
[cell setNeedsLayout];
return cell;
}
I'm using an iPhone 6 and iOS 8. I'm also using storyboard and set the UITableViewCell style to Subtitle.
OK, now that we've found the problem (with the nil phone number text on the person) you could solve it a couple of ways.
It seems that you don't want to set the text to blank. I imagine this is due to the fact that it lays out the cell in an odd way with the title pushed up to the top but nothing underneath it. Understandable.
So, you could create a custom UITableViewCell subclass. In it you can manage the layout yourself and if the number is nil lay it out one way and if it has a phone number lay it out a different way.
An easier way would be to use two different prototype cells instead.
In the storyboard create two prototype cells.
One with type Basic and give it a reuseIdentifier noPhoneNumberCell.
The other with type Subtitle and a reuse identifier phoneNumberCell.
Then in the code you can do something like this...
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
Person *person = [_persons objectAtIndex:indexPath.row];
UITableViewCell *cell;
if (person.phone) {
cell = [tableView dequeueReusableCellWithIdentifier:#"phoneNumberCell" forIndexPath:indexPath];
cell.detailTextLabel.text = person.phone;
} else {
cell = [tableView dequeueReusableCellWithIdentifier:#"noPhoneNumberCell" forIndexPath:indexPath];
}
cell.textLabel.text = person.name;
return cell;
}
This will now create two queues of cells. One for people with phone numbers and one for people without.
This way you don't mix the two and so avoid the problem you are facing.
[cell.detailTextLabel sizeToFit];

UILabel does not render in prototype cell

I have a UIViewController that contains a UITableView. In my table view I have a prototype cell in which I want to place custom labels. I cannot get any of my custom labels to render in the cell. The datasource and tableview delegates are connected and functioning properly. For my first attempt, I dragged a UILabel control onto my prototype cell. I set its tag to 1000. Here is my code to populate the cells:
-(UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *cellID = #"cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellID];
UILabel *customLbl = (UILabel*)[cell viewWithTag:1000];
if(indexPath.section == 0){
[cell.textLabel setText:[rData.currentHeightReadings objectForKey:[heightKeys objectAtIndex:indexPath.row]]];
[customLbl setText:#"CFS"];
} else {
[cell.textLabel setText:[rData.currentFlowReadings objectForKey:[flowKeys objectAtIndex:indexPath.row]]];
[customLbl setText:#"Ft."];
}
return cell;
}
The default textLabel for each cell renders as it should. However, the custom label does not appear. I verified that the prototype cell was actually rendering by changing the background color of the cell's content view. In my story board I have set the prototype cell's reuse identifier to match my code. The style is set to 'Custom.' What else should I be doing? Thanks!
Verify that your autolayout constraints are correct such that the UILabel is really positioned where you expect it.
I had the same issue once and I've solved it by not calling any methods to cell.textLabel property. Just don't set its text in any way.
Try it out and report back.
Try this:
UILabel *customLbl = (UILabel*)[cell.contentView viewWithTag:1000];

IOS7 Custom TableViewCell will not appear

I am trying to create a project with a custom UITableViewCell. The custom cells never load, they're just blank. At this point in the project what I'm trying to do is placing a UITableViewCell in a .xib, designing it the way I want and specifying its reuse identifier along with tag IDs for the components so that I can use them in code later on.
I've googled a ton and found several tutorials that look like what I want to do, along with many SO questions that have answers that seem applicable. At this point it's probably just my head spinning with too many different angles and solutions.
This is my current attempt at trying to register the custom cell with my UITableView, yet when running this on a device the rows in the table view are entirely blank.
UITableViewCell* cell = [self.tableView dequeueReusableCellWithIdentifier:#"MyCell"];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"MyCell"];
}
UILabel* l1 = (UILabel*)[cell viewWithTag:1];
UILabel* l2 = (UILabel*)[cell viewWithTag:2];
UILabel* l3 = (UILabel*)[cell viewWithTag:3];
l1.text = #"Foobar";
l2.text = #"Foobar";
l3.text = #"Foobar";
I'm pretty certain that I've hooked up all the properties and such correctly, but at this stage I need a fresh pair of eyes to point out the facepalm for me.
The interesting files are FilmerView.m/h/xib and the cell is in FilmerViewCell.xib. When running the app this TableView is in the second tab of the tab bar controller.
Project:
http://speedy.sh/WhhpP/test12.zip
I can't provide a full answer atm but look up the tableview method. registerNib:forCellReuseIdentifier:
Also, stop using that dequeue method. Use the one that includes the indexPath.
Then you don't have to check if the cell is nil afterwards.
EDIT
In viewDidLoad (or somewhere like that)...
UINib *cellNib = [UINib nibWithNibName:#"MyCustomCellXibFileName" bundle:[NSBundle mainBundle]];
[self.tableView registerNib:cellNib forCellReuseIdentifier:#"CellIdentifier"];
Now in the table view datasource method...
- (UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"CellIdentifier" forIndexPath:indexPath];
// no need to check cell == nil.
// this method is guaranteed to return a non nil cell.
// if it doesn't then the program will crash telling you that you need to...
// register a class or nib (but we just did this in viewDidLoad) :D
// configure your cell here...
[self configureMyCell:(MyCustomCell *)cell atIndexPath:indexPath];
return cell;
}
- (void)configureMyCell:(MyCustomCell *)cell atIndexPath:(NSIndexPath *)indexPath
{
cell.nameLabel.text = #"Hello, world";
}
Hope this helps.
Make sure that you have set datasource and delegate properties of your tableView.
Make sure that you have implemented (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section method and it returns a positive value (>0).
Evaluate the following:
Is the ReuseIdentifier set in the XIB. See Properties Tab in Interface Builder on the right when selecting the cell.
Are the AutoresizingMasks set properly for the labels to be visible?
WrapModes: Which did you select? When having wrapmode WrapWord, is the font size too large for the text to be moved in the next line becoming invisible?
Set the background color of the UITableViewCellss content view to something else than white or transparent, as well as the background colors of the labels to see if the cell is even there.
Manually call numberOfRowsInSection on your table, pass the proper NSIndexPath identifying the target section and see if its greater 0 to confirm that the TableView even attempts to load the data, thus, the cells. ( Alternatively set a breakpoint in the method or do a NSLog. )
Do a NSLog in cellForRowAtIndexPath to confirm that the cell returned is not nil and the method is even called!

self.tableView reloadData is not working to vertically center my label text

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"MyCell";
MyCustomCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
if (cell == nil)
cell = [[MyCustomCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
Movie *movie = [self.movies objectAtIndex:indexPath.row];
cell.title.text = movie.title;
cell.subtitle.text = movie.subtitle;
cell.subtitle.numberOfLines = 0;
[cell.subtitle sizeToFit];
return cell;
}
I am calling reloadData from two places. One is from the end of a loadInitialData function, which is called from viewDidLoad.
A second one is being called from viewDidAppear, although this is inconsequential to my problem, because it existed before it and exists without it.
I initially load 3 rows of sample data, with titles and subtitles. Now what happens is my subtitle text is vertically centered when this window first launches. If I grab the table and scroll is high up, all of a sudden my [cell.subtitle sizeToFit] goes into action, and my text goes to the top vertically, which is desired.
So my issue is... why is the text vertically centered from the beginning? reloadData doesn't work either. When I return from adding a new row, all rows but the newly added row are vertically aligned to top as they should. The new row is incorrectly vertically centered.
Why doesn't this work? Everything seems good. New data is added etc. Via NSLog statements, I have verified numberOfRowsInSection is immediately called after reloadData is called.
So why does the aligning of the text vertically to the top not work?
Thanks!
This is probably because the UITableViewCell has not yet been layed out and so it does not have a size yet. Try doing the sizeToFit in this UITableViewDelegate method
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
I am not sure this will work, but it worth trying.
Add [cell setNeedsLayout]; before you return the cell so it will layout the cell before presentation.

Custom dynamic TableViewCell text positioning

I have a dynamic TableView that looks like this.
However, I'd like to position the text more neatly, like this.
Here's the code I'm currently using:
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier =#"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
[cell.textLabel setFont:[UIFont fontWithName:#"HelveticaNeue-Light" size:17.0f]];
cell.textLabel.text=[[self.responseArray objectAtIndex:indexPath.row]objectForKey:#"name"];
return cell;
}
I've experimented with putting a label into the TableViewCell that's positioned where I want the dynamic text to be, but I've been unsuccessful in calling it in my code. How can I do this?
You should create a custom cell subclass. This subclass should have an #property in the .h file which makes your custom label available. In the .m (or XIB) you create (or connect) the label to the property (outlet).
Now, instead of using cell.textLabel you use cell.customTextLabel. Just remember to register the custom cell class against your CellIdentifier.
You can also configure the font and size on the label in the cell .m (or XIB) so you don't need to do it in code.
You will also want to change to:
CustomTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
so that the compiler knows that class the cell is (and thus what properties it has).
There is no need to create subclass of UITableViewCell. Coz, you want just change origin of your text.
I recommend to add a UILabel to your cell as subview.
cell.textLabel.text = #"";
UILabel *textLabel = [[UILabel alloc] initWithFrame: CGRectMake(10,10,300,20)];
textLabel.text = #"Text here";
[cell.contentView addSubview:textLabel];
2-3 lines only and you needn't create a subclass.

Resources