Auto Layout UILabels - ios

I have three UILabels in my custom UITableViewCell.
It might be that some UILabels will be empty (label.text == #"")
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"EventCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
NSString *key = [[keysArray objectAtIndex:indexPath.section] description];
UILabel *nameLabel = (UILabel *)[cell viewWithTag:100];
namelabel.text = #"Label 1";
UILabel *locationLabel = (UILabel *)[cell viewWithTag:101];
location.text = #"Label 2";
UILabel *timeLabel = (UILabel *)[cell viewWithTag:102];
timeLabel.text = #"";
return cell;
}
How can I centre all non-empty UILabels vertically in the cell using auto-layout?
This is how it looks with three labels
How it looks when one of UILables is empty
And this is how I want it to look:

This is tricky to achieve, but a simple shortcut may be to have a single label instead, with three lines of text, constrained to fill the whole height of the cell. The label will then auto-center its contents vertically.
You'd have three string properties on the cell instead of three labels, and your setters would build the final string (using \n for new lines) and set the label's text.
If each line of text has different styling, no problem, as you can use attributed strings.

Related

Constraints not working when using viewWithTag to get labels inside UITableviewCell

I really can't get my head around why this isn't working properly.
I have a TableViewController with dynamic prototypes. I put 4 labels in a prototype named "InfoCell", and gave them constraints.
If i run the app with the following cellForRowAtIndexPath:
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *cellIdentifier = #"InfoCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
return cell;
}
what I get is this. Everything looks fine 'til now
I did this just to check that the labels were being displayed in the right place. The page is supposed to show 2 cells, so everything looks fine.
Now, the problems start when I try to get a reference to the labels in order to change the text. Even without actually changing the text, if my code looks like this:
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *cellIdentifier = #"InfoCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
UILabel *nameLabel = (UILabel *)[cell viewWithTag:10];
UILabel *surnameLabel = (UILabel *)[cell viewWithTag:20];
UILabel *roleLabel = (UILabel *)[cell viewWithTag:30];
UILabel *spouseNameLabel = (UILabel *)[cell viewWithTag:40];
[cell addSubview:nameLabel];
[cell addSubview:surnameLabel];
[cell addSubview:roleLabel];
[cell addSubview:spouseNameLabel];
return cell;
}
I get this. Labels' positions went nuts
I tried, for example, to change the frame of each label programmatically,
nameLabel.frame = CGRectMake(15.0, 50.0, 120.0, 20.0)
but it just doesn't do anything, I suppose because auto-layout is enabled... but I'm too far into the project to disable auto-layout. Plus I've seen the use of viewWithTag as I wrote above working without the need to re-locate the labels programmatically, so it bugs me not to know what's really happening there!
Remember that when you have constraints added on any of the UI object, you can't change the frame of that object by changing its CGRect. In fact, you should change its constraint value.
Now the problem in your code is ,
[cell addSubview:nameLabel];
[cell addSubview:surnameLabel];
[cell addSubview:roleLabel];
[cell addSubview:spouseNameLabel];
above 4 lines. When you have added a UILabel in storyboard, why are you adding them again by using addSubview method ? Remove above 4 lines, and to set text on your UILabel , you already have a reference which you are accessing by using their tag values. So your method should looks like as below.
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *cellIdentifier = #"InfoCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
UILabel *nameLabel = (UILabel *)[cell viewWithTag:10];
UILabel *surnameLabel = (UILabel *)[cell viewWithTag:20];
UILabel *roleLabel = (UILabel *)[cell viewWithTag:30];
UILabel *spouseNameLabel = (UILabel *)[cell viewWithTag:40];
nameLabel.text = #"";
surnameLabel.text = #"";
roleLabel.text = #"";
spouseNameLabel.text = #"";
return cell;
}

Table View not changing dynamically on initial load

I am trying to create a table with unique styling so that my label size dynamically changes with the content. I was able to get the cell to change style after it has been dequeued once (ie once I scroll down to a new page, those cells are formatted and then when I scroll back up the cells are formatted) but cannot seem to do this one the initial load. The labels are scoped only to that method because anytime I tried to make them more available, it caused the storyboard to fail.
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
NSDictionary *pastVerse = [self.pastVerses objectAtIndex:indexPath.row];
UILabel *label;
label = (UILabel *)[cell viewWithTag:1];
label.text = [pastVerse valueForKey:#"reference"];
label = (UILabel *)[cell viewWithTag:2];
label.text = [pastVerse valueForKey:#"version"];
label = (UILabel *)[cell viewWithTag:3];
label.text = [pastVerse valueForKey:#"verse"];
[label setNumberOfLines:0];
[label sizeToFit];

Change the height dynamically on UITableViewCell's based on 1 label?

How can I scale UITableViewCells based on the amount of content in them? In my cells I use 3 labels which represent a forum. The labels are named "alias", "date", and "comments". The third label comments, can be any number of rows. Therefore, my cells need to become dynamically depending on the amount of text(size) it is in the "comments" label. Below is my relevant code:
- (UITableViewCell *)tableView:(UITableView *)pTableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"ForumthreadCell";
UITableViewCell *cell = [pTableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
Feedback *item = [self.items objectAtIndex:indexPath.row];
UILabel *aliasLabel = (UILabel *)[cell viewWithTag:1];
UILabel *commentLabel = (UILabel *)[cell viewWithTag:2];
UILabel *dateLabel = (UILabel *)[cell viewWithTag:3];
[aliasLabel setText:item.alias];
[commentLabel setText:item.comment];
[dateLabel setText:[self.dateFormatter stringFromDate:[NSDate dateWithTimeIntervalSince1970:(double)item.time]]];
commentLabel.numberOfLines = 0;
[commentLabel sizeToFit];
return cell;
}
In this method am I supposed to set the tableViewCell's height depending on commentLabel height.. The only problem is I am not sure how to do it?
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (????) {
return ????;
//return [indexPath row] + 50;
}
return ????;
}
I need help from someone that tries to take a look at my code and give examples how I can make this work. After all, its only 1 label.... I have already looked at several tutorials but not been able to make it work... Thanx for your time and help.
This is an old screen with some old code. This is more or less what the forum looks like now: http://tinypic.com/view.php?pic=16h7me9&s=6
What you need is a way to calculate the size of a text rendered with a specific font. Luckily, UIKit provides you with exactly this via the various sizeWithFont: methods in NSString UIKit Additions.

UILabel in a Prototype Cell is not updated from code

I have 2 UILabels in a Prototype Cell designed in the Storyboard. Both have their designated tag number (1000 and 1001). When I write the tableView cellForRowAtIndexPath: method it seems that one of the labels is receiving the relevant NSString and the other one doesn't.
Here is the code:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"ContentCell";
UITableViewCell * cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
ContentObject * contentObject = [contentPackageManager.contentObjectsArray objectAtIndex:[indexPath row]];
//contentPackageManager is a class that holds an NSArray of ContentObjects (it does a few other things, but they are not relevant for this method...)
//ContentObject is a class that holds several attributs such as: NSString*name, NSString*type, etc...
UILabel *nameLabel = (UILabel *)[cell viewWithTag:1000];
nameLabel.text = contentObject.name; //this line works OK
UILabel * typeLabel = (UILabel *)[cell viewWithTag:1001];
typeLabel.text = contentObject.contentType; //this is the PROBLEMATIC one - no effect on the actual UILabel
return cell;
}
Is anyone familiar with this issue?
Am I doing something wrong?
Please check if contentObject.contentType is not null.

UILabel won't wrap

I'm having a problem with my iOS app and getting a UILabel in a UITableViewCell to wrap. The text shows but it will only display on one line.
Here is my code:
- (UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Cell"];
UILabel *noteLabel = (UILabel *)[cell.contentView viewWithTag:2];
NSDictionary *contact = [jsonResults objectAtIndex:indexPath.row];
noteLabel.lineBreakMode = UILineBreakModeWordWrap;
noteLabel.numberOfLines = 0;
noteLabel.text = [contact objectForKey:#"note"];
return cell;
}
I believe the problem has something to do with this line:
UILabel *noteLabel = (UILabel *)[cell.contentView viewWithTag:2];
I'm not sure how else to get the label from a tag and I think this line won't let me change the labels properties.
You may need to set the label's height:
- (UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Cell"];
UILabel *noteLabel = (UILabel *)[cell.contentView viewWithTag:2];
NSDictionary *contact = [jsonResults objectAtIndex:indexPath.row];
noteLabel.lineBreakMode = UILineBreakModeWordWrap;
noteLabel.numberOfLines = 0;
noteLabel.text = [contact objectForKey:#"note"];
//Note: adjust the proper width to be constrained to
CGSize size = [noteLabel.text sizeWithFont:noteLabel.font forWidth:150 lineBreakMode:noteLabel.lineBreakMode];
CGRect labelFrame = noteLabel.frame;
labelFrame.size = size;
noteLabel.frame = labelFrame;
return cell;
}
Time has moved on since 2012. In the current Xcode 5 world, height is automatically expanded for the multiple lines if numberOfLines is set to 0 in either code or in Interface Builder. One thing that can prevent the multiple lines from being displayed in this scenario is if there is an AutoLayout height constraint set, in Interface Builder or in code. In this scenario, it will look like a label that has been truncated, though in contrast to a truncated label it will not end with an ellipsis (...).
In order for AutoLayout to function as expected, you would not normally want to set a higher height to the UILabel, unless you knew that UILabel would always have multiple lines.
What made the difference for me was setting the label's preferredMaxLayoutWidth.
https://developer.apple.com/library/ios/documentation/UIKit/Reference/UILabel_Class/#//apple_ref/occ/instp/UILabel/preferredMaxLayoutWidth

Resources