Line breaks not working in UILabel - iphone

I'm loading some help text from a plist and displaying the same in the form of UILabels housed in a UIScrollView. Portion of the code follows:
UILabel *sectionDetailLabel = [[[UILabel alloc] initWithFrame:CGRectMake(34, myOriginForThisSection, 286, 20)] autorelease];
sectionDetailLabel.backgroundColor = [UIColor clearColor];
sectionDetailLabel.numberOfLines = 0;
sectionDetailLabel.font = [UIFont systemFontOfSize:12];
sectionDetailLabel.textColor = [UIColor blackColor];
sectionDetailLabel.textAlignment = UITextAlignmentLeft;
sectionDetailLabel.lineBreakMode = UILineBreakModeWordWrap;
[baseScrollView addSubview:sectionDetailLabel];
[sectionDetailLabel setText:myStringForThisSection];
[sectionDetailLabel sizeToFit];
While any 'long' text is getting wrapped into multiple lines correctly, I'm unable to manually insert any line-breaks using newline '\n' characters in 'myStringForThisSection'. I only see the characters '\' and 'n' printed in the UILabel wherever I wanted the line-break, instead.
I looked this up and the general consensus seemed to be that setting numberOfLines to 0, setting the lineBreakMode to a valid value and invoking sizeToFit (or setting the frame of the UILabel based on sizeWithFont:) should do. All of which I seem to be doing in the code above - and works perfectly when fitting long strings of unknown length into multiple lines on the UILabel. So what could be missing here?
Note: All the variables used - baseScrollView, myStringForThisSection and myOriginForThisSection - were loaded before the above code began executing, and work fine.

UILabel doesn't interpret the escape sequence \n. You can insert the real character that represents the Carriage Return and/or the Line Feed. Make a char to hold your newline and then insert it.
unichar newLine = '\n';
NSString *singleCR = [NSString stringWithCharacters:&newLine length:1];
[myStringForThisSection insertString:singleCR atIndex:somePlaceIWantACR];
As long as your myStringForThisSection is mutable, that should do it.

I had trouble with Scot Gustafson's answer above in XCode 4.3
Try this instead:
unichar chr[1] = {'\n'};
NSString *cR = [NSString stringWithCharacters:(const unichar *)chr length:1];
Then use in your code something like this:
self.myLabel.text = [NSString stringWithFormat:#"First Label Line%#Second Label Line", cR];

I couldn't get Scott & DoctorG's solution to work (though I didn't spend too much time trying), but here's the simple solution that works for me when I'm extracting escaped text from an xml file.
Inside my string function class, I define:
+(NSString)escapeXml:(NSString*)string {
return [string stringByReplacingOccurrencesOfString:#"\\n" withString:#"\n"];
}

Related

Know where a UILabel splits a string when its multi-line property is on

Have a problem, need to assign some text to a UIButton's title. Have set the buttons line break mode to NSLineBreakByCharWrapping so that the string is separated only by characters at end of each line. But i need to insert an hyphen at the end of the line to show continuity of the word.
Heres what i tried -
// Initialize the button
titleButton.titleLabel.lineBreakMode = NSLineBreakByCharWrapping;
titleButton.titleLabel.backgroundColor = [UIColor yellowColor];
[titleButton.titleLabel setFont:[UIFont fontWithName:#"Helvetica-Bold" size:15]];
// Make the string here
NSMutableString *titleString = [[NSMutableString alloc] initWithString:#"abcdefghijklmnopqrs tuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz"];
// Insert hyphens
int titleLength = [titleString length];
int hyphenIndex = 19;
while (hyphenIndex<titleLength) {
UniChar charatIndex = [titleString characterAtIndex:hyphenIndex];
if ((charatIndex - ' ') != 0) { // Check if its not a break bw two words
[titleString insertString:#"-" atIndex:hyphenIndex]; // else insert an hyphen to indicate word continuity
}
hyphenIndex += 19; //Since exactly 20 char are shown in single line of the button's label.
}
//Set the hyphenated title for the button
[titleButton setTitle:titleString forState:UIControlStateNormal];
[titleString release];
This is the closest i could get.
Any help would be greatly appreciated.
Try NSAttributedString
It give a great possibilities for working with strings.
WWDC 2012-230
For example:
- (NSUInteger)lineBreakBeforeIndex:(NSUInteger)index withinRange:(NSRange)aRange
//Returns the appropriate line break when the character at the index won’t fit on the same line as the character at the beginning of the range.
your second word's length is more the length of line (width of button) thats why this happen.
pasting hyphens is not very good idea. You should split your string on parts with size that fits button's width by using than add hyphens if needed
[String sizeWithFont:font constrainedToSize:Size lineBreakMode:LineBreakMode]
The main idea is to get portion of initial string (add hyphen if word breaks), check if its width fits button's width. If width is smaller, try bigger part, else if fits -- process further part
See my answer here for how to use NSParagraphStyle and NSAttributedString to get a UILabel that breaks with hyphens: https://stackoverflow.com/a/19414663/196358

Showing emoji in a UILabel?

Not sure what I'm missing here, and searching hasn't helped me. I want to display emoji characters in a UILabel, and this isn't doing it:
UILabel *label = [[UILabel alloc] init];
label.font = [UIFont fontWithName:#"AppleColorEmoji" size:16.0];
label.text = [NSString stringWithFormat:#"%C", 0x1F431];
// ... etc.
Works fine with other non-letter unicode characters, e.g. chess pieces, but not with any emoji characters that I have tried.
To use Emoji's just press Control+command+space (⌃⌘Space). No need of using unicode for emoji.
You are probably not using the correct encoding for your emoji characters. For instance in your example I think you are looking for something like this:
label.text = [NSString stringWithFormat:#"%C", 0xe04f];
Have a look at this table to get the encodings you need.
In xcode just go to the top bar and click EDIT > EMOJIS & SYMBOLS and an emoji box will pop up and you can literally add it to any text in the app, even works in the interface builder if you need to add it to the text of a uilabel there.
In Swift you can do:
label.text = "🐈"
Be sure to include the quotes. Otherwise you'll be setting the text to whatever is in the variable.
The following would display as "cat":
let 🐈 = "cat"
label.text = 🐈
The unicode 6.1 encodings work as well, but you would have to specify them like this:
label.text = #"\U0001F431";

Escaping the #" " characters in Objective C

I'm trying to set the background image of a view based on a passed "artistID." Here is my code so far:
NSString *backgroundImageName = [[NSString alloc]initWithFormat:#"artistbackground%i.png",_artistID];
self.view.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:backgroundImageName]];
NSLog(#"%#",backgroundImageName);
unfortunately, for the parameter in ImageNamed, I'm passing in:
artistibackground1
instead of:
#"artistbackgound1"
Any ideas on how to escape the # and the quotes??
Thanks!!
self.view.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:[NSString stringWithFormat:#"#%#",backgroundImageName]];
Essentially make two strings, it will add the #"" in the second.
You should use \ before the character you want. An example:
NSLog(#"\#\"Try\"");
The code prints
#"Try"
Don't forget that even string constants are NSString objects in Objective-C. This is part of the magic! I frequently see programmers new to the language writing this line:
[NSString stringWithFormat:#"#%#",backgroundImageName];
But you can simplify this line to:
[#"#" stringByAppendingString:backgroundImageName];
Magic!

Appending data in UITextField programmatically

I am creating a report & printing the same on a UITextView.My report has some titles and there respective subtitles. I am printing 1st title then its subtitle & then second title and its subtitle and so on. I want different font and font sizes for the titles and subtitles.
But the problem is the text field always prints the last subtitle.If any one know solution to this problem,let me know.
Here is what i have dome in my .m file
- (void) printData {
// data is UITextView object
[data setFont:[UIFont fontWithName:#"Helvetica" size:15]];
NSString *title = #"TITLE" ;
data.text = title;
[data setFont:[UIFont fontWithName:#"Arial" size:15]];
NSString *subtitle = #"SUBTITLE" ;
data.text = subtitle;
}
First of all I would Use UITextView instead of UITextField, as it is build for long text.
If you just keep calling the method text of either UITextField or UITextView, the currently residing text will be replaced with your last text. To avoid that you have to append new text to the text that is already residing in the UITextField or UITextView.
NSString *appendThisText = #"subtitle";
self.myTextView.text=[NSString stringWithFormat:#"%#%#", self.myTextView.text, appendThisText];
As for the fonts. The font property applies to the entire UITextField and UITextView content.
What you could do in your case is to use UIWebView and render your text using HTML.
Another way:
[myTextView setText:[myTextView.text stringByAppendingString:#"my string"]];
Or with a \n line break:
[myTextView setText:[myTextView.text stringByAppendingString:#"\nMy string"]];

Get truncated text from UILabel

Is there anyway I can get the truncated version of the text for a UILabel?
In short, I have a paragraph of text, and two UILabels - label A, which is 2 lines long, and label B, which is a variable height. Label A is above label B. The idea is that label A shows the first two lines of the paragraph of text, and upon a certain user action, label B because visible and displays the rest of the text.
I'm having trouble determining what should go in label B, as I don't know what's being shown in label A. I'd need to also remove the "..." from label A.
Note: I realize this is a bit convoluted but there are some good reasons for it, which I won't clutter up the question with.
I wonder if you could use the methods in the NSString UIKit Additions to figure out how much fits into label A.
A crude way might be to start with the first character of your text and test for the size it would take up (-sizeWithFont:forWidth:lineBreakMode: maybe?) and then keep adding characters one at a time until it doesn't fit into your label A any more.
I hope somebody else can come up with a better way to do this, but the above should work.
Update
Last night I looked a bit into Core Text for my own app and came across CTFramesetterSuggestFrameSizeWithConstraints. You could maybe use this to figure out how much of your string fits into the label, by looking at the fitRange in that function.
Update 2:
I think this should work, but I have just typed this in here, so it may not even compile:
UIFont *uiFont = [UIFont systemFontOfZise:13.0f]; // whichever font you're using
CTFontRef ctFont = CTFontCreateWithName((CFStringRef)uiFont.fontName, uiFont.pointSize, NULL);
NSDictionary *attr = [NSDictionary dictionaryWithObject:(id)ctFont forKey:(id)kCTFontAttributeName];
CFRelease(ctfont);
NSAttributedString *attrString = [[NSAttributedString alloc] initWithString:yourLabelText attributes:attr];
CTFrameSetterRef frameSetter = CTFrameSetterCreateWithAttributedString((CFAttributedStringRef)attrString);
[attrString release];
CFRange fitRange;
CTFrameSetterSuggestFrameSizeWithConstrains(
frameSetter,
CFRangeMake(0, 0),
NULL,
CGSizeMake(labelWidth, labelHeight),
&fitRange);
CFRelease(frameSetter);
CFIndex numberOfCharactersThatFit = fitRange.length;
thanks to Thomas Müller
be sure to set line break mode the myLabel to this:
myLabel.lineBreakMode = NSLineBreakByWordWrapping;
by this method you can get chunked strings that actually fit in the constrained size.
Here is the baked code:
- (NSArray *)truncate:(NSString *)text
{
NSMutableArray *textChunks = [[NSMutableArray alloc] init];
NSString *chunk = [[NSString alloc] init];
CTFramesetterRef frameSetter;
UIFont *uiFont = [UIFont systemFontOfSize:17.0f];
CTFontRef ctFont = CTFontCreateWithName((__bridge CFStringRef)uiFont.fontName, uiFont.pointSize, NULL);
NSDictionary *attr = [NSDictionary dictionaryWithObject:(__bridge id)ctFont forKey:(id)kCTFontAttributeName];
NSMutableAttributedString *attrString = [[NSMutableAttributedString alloc] initWithString:text attributes:attr];
CFRange fitRange;
while (attrString.length>0) {
frameSetter = CTFramesetterCreateWithAttributedString ((__bridge CFAttributedStringRef) attrString);
CTFramesetterSuggestFrameSizeWithConstraints(frameSetter, CFRangeMake(0,0), NULL, CGSizeMake(myLabel.frame.size.width, myLabel.frame.size.height), &fitRange);
CFRelease(frameSetter);
chunk = [[attrString attributedSubstringFromRange:NSMakeRange(0, fitRange.length)] string];
[textChunks addObject:chunk];
[attrString setAttributedString: [attrString attributedSubstringFromRange:NSMakeRange(fitRange.length, attrString.string.length-fitRange.length)]];
}
return textChunks;
}
For Label A, calculate approximate character that should fit perfectly for two lines, for the particular font you are using.
For label B, set variable Height that the whole text must fit into it.