Xcode 4.2 - UILabel Word Wrap - objective-c

I know people have asked this question a bunch of times alrdy on Stack, but the usual answer of changing "Lines: 0" and selecting "Line Breaks: Word Wrap" just isn't fixing it for me.
I am using Xcode 4.2 with a Storyboard. I have placed a UILabel on a View Controller and resized it to cover most of the View. I have changed "Lines" value to 0 and "Line Breaks" value to Word Wrap.
I have tried \n in my string: #"This is my label text \n that's supposed to wrap."
Any ideas??
EDIT: I wasn't declaring any of the label's properties in my implementation file, only on the storyboard, so I have tried the following... But with no luck ;\ (font name and size and alignment work, but number of lines and break mode seem to do nothing.)
lblText.numberOfLines = 0;
lblText.font = [UIFont fontWithName:#"Helvetica" size:(15.0)];
lblText.lineBreakMode = UILineBreakModeWordWrap;
lblText.textAlignment = UITextAlignmentLeft;

Try this
[lblText setFrame:CGRectMake(10, 21, 100, 250)];
lblText.text =#"This is my label text \n that's supposed to wrap.";
lblText.numberOfLines = 3;
lblText.font = [UIFont fontWithName:#"Helvetica" size:(15.0)];
lblText.lineBreakMode = UILineBreakModeWordWrap;
lblText.textAlignment = UITextAlignmentLeft;

Related

UITextView renders custom font incorrectly in iOS 7

My app uses a UITextView to input Syriac text (Estrangelo font), but UITextView renders some letters incorrectly like this:
I tested it with a UILabel and a UITextView. UILabel displays it correctly, but UITextView incorrectly displays the top dots and moves them to the bottom (see the above result).
This problem only occurs in iOS 7 and does not occur in iOS 6. Please tell me if there's any way to fix the problem.
This is my test code
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 100, 40)];
label.center = CGPointMake(self.view.center.x, self.view.center.y-40);
label.font = [UIFont fontWithName:#"East Syriac Adiabene" size:24];
label.text = #"ܩ̈ ܡ̄ ܬ̇ ܒ̃";
[self.view addSubview:label];
UITextView *textView = [[UITextView alloc] initWithFrame:CGRectMake(0, 0, 100, 40)];
textView.center = CGPointMake(self.view.center.x, self.view.center.y+40);
textView.font = [UIFont fontWithName:#"East Syriac Adiabene" size:24];
textView.text = #"ܩ̈ ܡ̄ ܬ̇ ܒ̃";
[self.view addSubview:textView];
I debugged this issue a little, and it seems to be a bug in the way NSLayoutManager layouts the text. As other answers pointed out, UITextView is build around TextKit since iOS7, and thus uses NSLayoutManager internally to layout text. UILabel uses Core Text to layout text directly. Both eventually use Core Text to render the glyphs.
You should open a bug report with Apple and post the number so people can duplicate it. The issue has not been fixed so far in iOS7.1 betas.
As a workaround, you can replace UITextView with other Core Text alternative editors, which layout and render directly with Core Text, where the issue does not exist.
I tested SECoreTextView, and it shows the text correctly. It implements a similar API to UITextView but internally uses Core Text.
Here is how it looks after swapping UITextView with SECoreTextView:
SETextView *textView = [[SETextView alloc] initWithFrame:CGRectMake(0, 0, 100, 40)];
textView.center = CGPointMake(self.view.center.x, self.view.center.y+40);
textView.font = [UIFont fontWithDescriptor:desc size:24];
textView.text = #"ܩ̈ ܡ̄ ܬ̇ ܒ̃";
textView.textColor = [UIColor blackColor];
textView.backgroundColor = [UIColor whiteColor];
textView.editable = YES;
[self.view addSubview:textView];
Some days ago, I had the same problem as yours in iOS 7 (but the font was different).
I set the FONT after setting the TEXT and it worked for me. So for your case:
textView.text = #"ܩ̈ ܡ̄ ܬ̇ ܒ̃"; // Setting the text.
textView.font = [UIFont fontWithName:#"East Syriac Adiabene" size:24]; // Setting the font and it's size.
It may seem silly, but it worked for me.
Also see this question/answer. There are many tips for using custom fonts with UITextView, which may be helpful for you.
EDIT :
iOS 7 also introduced a new selectable property on the UITextView for enabling text selection. So make sure you have done the following:
self.textField.editable = YES;
self.textField.selectable = ON;

UILabel text layout when wrapping is "wrong" in iOS 7

The screen shot below is in iOS 7. label1 (yellow, top) is drawn with the text origin below the top left of the its frame and clipped at the bottom. In iOS 5/6 the text origin is the top left of the label frame. label2 and label3 render and layout as expected.
Here is the code to generate this view:
- (void)loadView
{
UIView *view = [[UIView alloc] initWithFrame:UIScreen.mainScreen.applicationFrame];
view.backgroundColor = UIColor.blueColor;
self.view = view;
UILabel *label1 = [UILabel new];
label1.backgroundColor = UIColor.yellowColor;
label1.font = [UIFont systemFontOfSize:16.0f];
label1.numberOfLines = 0;
label1.lineBreakMode = NSLineBreakByWordWrapping;
label1.frame = CGRectMake(50, 100, 200, 18);
label1.text = #"This text is too long to fit on one line.";
[self.view addSubview:label1];
UILabel *label2 = [UILabel new];
label2.backgroundColor = UIColor.greenColor;
label2.font = [UIFont systemFontOfSize:16.0f];
label2.numberOfLines = 0;
label2.lineBreakMode = NSLineBreakByWordWrapping;
label2.frame = CGRectMake(50, 150, 200, 36);
label2.text = #"This text is too long to fit on one line.";
[self.view addSubview:label2];
UILabel *label3 = [UILabel new];
label3.backgroundColor = UIColor.orangeColor;
label3.font = [UIFont systemFontOfSize:16.0f];
label3.numberOfLines = 0;
label3.lineBreakMode = NSLineBreakByWordWrapping;
label3.frame = CGRectMake(50, 200, 200, 18);
label3.text = #"This text is short.";
[self.view addSubview:label3];
}
QUESTION: Why is this different in iOS 7 and what label properties do I need to change to have the text in label1 render starting from the top left of its frame as expected.
I figured it out. Rather than delete my question, I'll answer it here so if anyone else runs into this they know what to do.
The label frames are hardcoded to specific sizes. In the case of label1, the height is 18. This bound is not tall enough to render a line of text with a system font at 16 points. iOS 5/6 apparently top align the text rect whereas in iOS 7 this causes unpredictable behavior. This fix is to ensure the label bounds are tall enough to display at least one line of text.
The sample code in the question was for the purposes of reproducing this problem. My actual app code calculates label heights based on desired number of lines with various other views positioned around the label so the frame is changed dynamically at run time. I fixed the problem in my app by ensuring the minimum label height can fit a single line of text.

Custom font in Navigation Bar Truncating uses semicolon not ellipses

I am trying to customize the font on my Navigation Bar. Everything is fine except for some reason, when the title is too long for the Navigation Bar, it gives me a semicolon instead of ellipses (...)
How do I get the ... to show that the title is cut off?
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0, 20, 240, 24)];
label.backgroundColor = [UIColor clearColor];
label.font = [UIFont fontWithName:#"My Font" size:20.0];
label.numberOfLines = 1;
label.lineBreakMode = NSLineBreakByTruncatingTail;
label.textAlignment = UITextAlignmentCenter;
label.textColor =[UIColor whiteColor];
label.text=#"Some Really Long Title Name That's Normally Dynamic";
self.navigationItem.titleView = label;
So I want the Navigation Bar to say "Some Really Long Titl..." However it keeps saying "Some Really Long Title ;"
Thanks!
The reason is that the '...' glyph you see is that, one unicode glyph. The font you are using either defines that incorrectly, or it does not define it at all. If you have some font editing tools, you can probably fix it but I don't know how. That character can be 'typed' on a Mac using option-;, probably why you see the ';'.

uilabel tail truncation

Im working on an ios app using objective c and i have an issue with uilabel that i could use some help with. Basically i have a label that can change size to fit the text that it will display but it has a max height that it can possible be. the label itself has a fixed width at all times. i have turned on UILineBreakModeWordWrap and UILineBreakModeTailTruncation to make the text fit and truncate but this causes the text to truncate the tail too early when it has only 1 word left to place. rather then moving it onto the next line when there is still room it just truncates it.
self.frame = CGRectMake(self.frame.origin.x, self.frame.origin.y, fixedWidth, 0);
self.lineBreakMode = UILineBreakModeWordWrap | UILineBreakModeTailTruncation;
self.numberOfLines = 0;
[self sizeToFit];
is there anyway of finding when the uilabel is actually truncating the text so i can then check the label height and add to it if there is still room ? I tried always adding an extra line to the height when there is room and this avoids the early truncation but then im left with inconsistent sizing of the over all label. any ideas on this would be great thanks
lineBreakMode is a switch. It can be either (for iOS6+) NSLineBreakByWordWrapping or NSLineBreakByTruncatingTail but not both.
But, to answer your question, you can find the size of some text using the class extensions in NSString+UIKit. Having found the size you could update the frame of the UILabel appropriately.
Using this method:
How to find UILabel's number of Lines
You could set the label to the max height, find out how tall the text is in that label and shrink it as necessary.
I have written a category for working with UILabel's truncation. Works on iOS 7 and later. Hope it helps !
#implementation UILabel (Truncation)
- (NSRange)truncatedRange
{
NSTextStorage *textStorage = [[NSTextStorage alloc] initWithAttributedString:[self attributedText]];
NSLayoutManager *layoutManager = [[NSLayoutManager alloc] init];
[textStorage addLayoutManager:layoutManager];
NSTextContainer *textContainer = [[NSTextContainer alloc] initWithSize:[self bounds].size];
textContainer.lineFragmentPadding = 0;
[layoutManager addTextContainer:textContainer];
NSRange truncatedrange = [layoutManager truncatedGlyphRangeInLineFragmentForGlyphAtIndex:0];
return truncatedrange;
}
- (BOOL)isTruncated
{
return [self truncatedRange].location != NSNotFound;
}
- (NSString *)truncatedText
{
NSRange truncatedrange = [self truncatedRange];
if (truncatedrange.location != NSNotFound)
{
return [self.text substringWithRange:truncatedrange];
}
return nil;
}
#end
I just came to a similar problem, and solved it with a very simple solution (tested on ios 8.4, xcode 7).
In IB (I use autolayout with some constraints):
set UIlabel numberOfLine = 1;
LineBrakeMode = TruncateTail
In Code:
label.numberOfLines = 2; // I can only display 2 row.
// I supposed you should know how many rows you can displayed.
label.preferredMaxLayoutWidth = label.frame.size.width;
[label sizeToFit];
Tadaa. That's it. Note that this only work with UILabel. With UIButton, it may not work (Haven't tested).

UILabel sizeWithFont: problem. Clipping italic text

I have created a UILabel that displays a single large character. Even with clipsToBounds = NO; I still get clipping.
See link: http://img341.imageshack.us/img341/5310/screenshot20100814at243.png
I used the following code:
CGSize fBounds = [myLabel.text sizeWithFont:cFont];
To get what should be the bounding rectangle of the font. And the label is drawn with:
myLabel = [[UILabel alloc] initWithFrame:CGRectMake(20, 20, 280, 300)];
myLabel.clipsToBounds = NO;
myLabel.numberOfLines = 1;
myLabel.textAlignment = UITextAlignmentCenter;
myLabel.adjustsFontSizeToFitWidth = YES;
myLabel.minimumFontSize = 10;
myLabel.text = #"A";
myLabel.font = [UIFont fontWithName:#"CourierNewPSMT" size:300];
myLabel.textColor = [UIColor blackColor];
myLabel.backgroundColor = [UIColor colorWithRed:1 green:.5 blue:0 alpha:.5];
In the image below, the size returned from sizeWithFont is rendered by the semi-transparent blue rectangle overlay. As you can see, with an italic font (in this case Verdana-BoldItalic), the character extends past what sizeWithFont returns. Further, the UILabel's frame (the orange color) also clips the character. Thoughts? Maybe I could override some text drawing routine. Also, not sure if this is the same problem as here:
UIButton.titleLabel clipping text problem
Use attributed text + indent...
Looks like this is an apple problem. Ended up doing custom drawing with CoreText.