iPhone UILabel - non breaking space - ios

Is there a way to use non breaking spaces in UILabel text?
For example, I have label with 2 lines and line breaking mode set to word wrap. The content for this label is read from database, where it's stored as a string. Now sometimes my text in label looks like that:
lorem ipsum some text
1
but I want to display it like that:
lorem ipsum some
text 1
so basicly, I need to force non breaking space between 'text' and '1'.
I've found some solution here, but I think it could work when the text is entered in source code file. In my case the text is in database.
Any suggestions?

Use the no-break space (\u00a0) ex: #"hello**\u00a0**world!"
post.text = [postText stringByAppendingString: #"1\u00a0hour\u00a0ago."];
U+00A0 / no-break space / Common Separator, space
from: http://en.wikipedia.org/wiki/Whitespace_character

For Swift:
let sentence = "Barcelona, Real Madryt, Juventus Turyn, Bayern Monachium"
let sentencewithnbsp = String(map(sentence.generate()) {
$0 == " " ? "\u{00a0}" : $0
})

In Swift 4 I had to use all caps: \U00A0
Example:
lorem ipsum some\U00A0text 1
Update Feb 2020 from the comments. Thanks to #corban:
In the Localizable.strings file it still needs to be \U00A0 - in code
you have to use \u{00a0}

If you want to get this to work in a .strings file, you can type OPTION + SPACE instead of a regular space.
.strings files are usually UTF-8 encoded, so if you open it in Hex view, you will see "C2 A0" in place of the special space character.

In Inspector set number of lines for Label as 3 or 4 What ever you require Then the Content will be displayed in multiple lines.

You may need to implement a custom word-wrapping function.
// pseudo-code
instring;
get len(instring)
if len > textedit.width*charFontSize
for (textedit.width*charFontSize ) // cycle through string
insert `\n` into inString at shortest whitespace
or something like that.

I don't think there's a simple way to do this with UILabel. Of course one way to achieve the same effect is to manually insert a "\n" before "text" in your example. Another option is to use a UIWebView with static HTML instead of the UILabel, so you can use an actual &nbsp.

Here's a Swift extension to fix an orphan in a string by replacing the last space with a non-breaking space:
extension String {
var replacingLastSpace: String {
if let lastSpace = range(of: " ", options: .backwards, locale: .current) {
return replacingCharacters(in: lastSpace, with: "\u{00a0}")
}
return self
}
}
Although note as of iOS 11, UILabels solve this problem automatically.

If this is not going to happen often, you can do this:
NSString *string = #"lorem ipsum some \ntext 1";
label.text = string;
You can dynamically generate where you put the \n using character counts, word counts etc...

Related

Shrinking text to fit one line label when using setAttributedTitle

I need to use subscript and superscript so I have used NSMutableAttributedString to offset specific characters.
I need an equivalent of:
mybutton.titleLabel?.minimumScaleFactor = 0.5
mybutton.titleLabel?.numberOfLines = 0
mybutton.titleLabel?.adjustsFontSizeToFitWidth = true
but for attributed strings?
Any starters much appreciated. Best wishes.

UILabel truncate tail and skip not complete word

I have a single line UILabel. It has width = screen width and the content now is (the content of UILabel can change)
You have 30 seconds to make an impression during an interview
Currently, my UILabel is truncated tail and the word "duration" is not complete
self.nameLabel.lineBreakMode = NSLineBreakByTruncatingTail;
What I want is I want my UILabel still truncating tail and only display complete word.
Like the image below
Any help or suggestion would be great appreciated.
You can do something like this:
let labelWidth = CGRectGetWidth(label.bounds)
let str = "You will have 30 seconds till you give us a good impression" as NSString
let words = str.componentsSeparatedByString(" ")
var newStr = "" as NSString
for word in words{
let statement = "\(newStr) \(word) ..." as NSString
let size = statement.sizeWithAttributes([NSFontAttributeName:label.font])
if size.width < labelWidth {
newStr = "\(newStr) \(word)"
}
else{
break
}
}
newStr = newStr.stringByAppendingString(" ...")
self.label.text = newStr as String
Idea is: we split words and try check the width while appending from the beginning + the string "..." till we found the a word that will exceed the size, in the case we stop and use this new string
Ideally this is not possible,with default UILabel, when you set lineBreakMode to TruncatingTail, depending on the space required by the letter/word the OS will truncate it, one solution to fix the issue you can use following properties depending on your match.
Minimum Font Scale -- Use this property to specify the smallest multiplier for the current font size that yields an acceptable font size to use when displaying the label’s text. If you specify a value of 0 for this property, the current font size is used as the smallest font size.
Minimum Font Size -- When drawing text that might not fit within the bounding rectangle of the label, you can use this property to prevent the receiver from reducing the font size to the point where it is no longer legible.
i am not sure but try it:
nameLabel.adjustsFontSizeToFitWidth = NO;
nameLabel.lineBreakMode = NSLineBreakByWordWrapping;
OR
If you are using storyboard follow these steps i tried this and it working fine
Open Attribute Inspector
Change Line Breaks to Truncate Tail then
Change AutoShrink to Minimum Font Size
here are my screenshots of label after and before applying these properties
new output

how to check if a text label is greater than another text label in Xcode

I am relatively new to xCode and I have 2 integer text labels Text1 and Text2 text.
I'm looking for some code that would compare if Text1.text is greater than Text2.text and then if another text field Text3.text would be equal to the value of Text1.text.
Appreciate any help.
In the attributes inspector I assume. Select the text, go to attributes inspector (top right corner at the utility area, forth in a row. Looks like a square head with ears) and check the size.
Well, if you want xcode to check the size, you'll need to make an if or switch statement. Use enums like .fontSize
The text fields are just views that display a string.
You can access the string that they contain via the text property:
NSString *text1 = _text1.text;
Now you have the string that is displayed in the textview ( "34" for example)
You can use the NSString method intValue to turn this string into an integer:
int text1Value = [text1 intValue];
You can now compare the value of this to another integer:
if (text1Value > 42) {
_textLargest.text = [NSString stringWithFormat:"%d", textValue1];
}
Main points:
Text fields are just views; you need to work with the data they are displaying rather than treat them as objects
You need to use the correct type for your comparison. The text field contains text but you need to convert it to a number to make it meaningful
You need to convert the number back into a string if you want it to appear in the text field's text property [NSString stringWithFormat:"%d", textValue1]
You can take and compare the int values as follows
if([Text1.text intValue] > [Text2.text intValue] )
{
Text3.text=[NSString stringWithFormat:"%#", Text1.text];
}

Why are the ranges for my formatted text shifting in iOS 7?

My app includes a text formatting tool that offers buttons for things like bold, italic and color and shows the formatted text by generating an NSAttributedString and setting that to the attributedText property of a UITextView. After the user selects text and taps a button, I get the selectedRange property of the UITextView, then get the current attributedText property of the UITextView, add another attribute to the text based on the selected range, and then assign it back to the attributedText property of the UITextView again.
Starting with iOS 7, my text formatting started displaying at the wrong location in the text, usually shifted a couple characters forward. After some testing I noticed that this only happened after an empty line (e.g., a paragraph of text with two line breaks after it) and the formatting was offset by one character for each empty line proceeding it.
After more testing I found that when I set the attributedText property for the first time, any sequence of two line breaks is changed to a line break, then a "line separator" character (Unicode 8232) and then the second line break. The new characters are definitely added by the attributedText assignment, as I can see from outputting the integer value of each character immediately before and immediately after that action. However, the selectedRange property of the UITextView ignores the line separator characters, so any range that it returns is now incorrect.
I've already found a workaround, which I'll add as an answer in a moment. I'm mainly posting this in case anyone else is having problems with it. Also, I've reported this to Apple as bug 15349335.
I wrote this method to adjust ranges returned by the selectedRange property to account for these extra line separator characters:
- (NSRange)adjustRangeForEmptyLines:(NSRange)range inText:(NSAttributedString *)text byChars:(int)chars {
int emptyLinesBeforeRange = 0;
int emptyLinesWithinRange = 0;
for (int i=0; i<(range.location + range.length); i++) {
int thisCharacter = [text.string characterAtIndex:i];
//NSLog(#"thisCharacter: %i", thisCharacter);
if (thisCharacter == 8232) {
if (i < range.location) {
emptyLinesBeforeRange++;
} else {
emptyLinesWithinRange++;
}
}
}
//NSLog(#"found %i + %i empty lines", emptyLinesBeforeRange, emptyLinesWithinRange);
range.location += (emptyLinesBeforeRange * chars);
range.length += (emptyLinesWithinRange * chars);
return range;
}
I can set the byChars argument to 1 or -1 depending on which way I want to adjust. This has been working for me for a few weeks now, but if anyone has an alternate solution, I'd be curious to see it.

UILabel lineBreakMode, break at specific character

Is there a way to break the text in a UILabel at a specific character say ";" ??
I don't want it to be broken with Word Wrap or character Wrap.
Sure, just replace all the occurrences of ";" with ";\n" before you show the string.
There is another way which will work in limited circumstances. You can replace your normal spaces (\U+0020) with non-breaking spaces (\U+00A0). This will allow you to limit the number of places your string breaks. For example if you had a string like;
I have a string with two sentences. I want it to preserve the sentences.
By carefully using non-breaking spaces you can get it to break like this;
I have a string with two sentences.
I want it to preserve the sentences.
HOW:
For Strings in InterfaceBuilder:
Go to System Preferences -> Keyboard -> Input Sources -> +
Select the category 'Others' and the keyboard 'Unicode Hex Input'
Select 'Add'
Make sure 'Show Input method in menu bar' is selected.
CLose System Preferences
Go back to XCode and find your string
Using the keyboard menu in your menu bar, select the Unicode keyboard
In your string select a space. Type Option+00a0. A space will appear when you've completed the 4 digit sequence. That space is a non-breaking space. Repeat for all spaces you need to.
For programmatic strings you can just add \U00A0 as appropriate.
You can use (\r) instead of newline (\n) to create a line break.
Set numberOfLines to 0 to allow for any number of lines.
yourLabel.numberOfLines = 0;
Like With in your case just replace ; with ;\n
NSString *string = #"This; is a; NSString";
string = [string stringByReplacingOccurrencesOfString:#";"
withString:#";\n"];
You can't break line using ; this character. if you want to break line then replace this character with \n character.
label.text=[label.text stringByReplacingOccurrencesOfString:#";" withString:#"\n"];
And make
label.numberOfLines = 0.
And Update the label frame
CGSize labelSize = [label.text sizeWithFont:label.font constrainedToSize:label.frame.size lineBreakMode:label.lineBreakMode];
label.frame = CGRectMake(label.frame.origin.x, label.frame.origin.y, label.frame.size.width, labelSize.height);
You can do with combination of newline character and line break.Check the following code,
self.testLabel.text = #"abc;\nabc;";
self.testLabel.numberOfLines = 0;
CGSize labelSize = [self.testLabel.text sizeWithFont:self.testLabel.font
constrainedToSize:self.testLabel.frame.size
lineBreakMode:self.testLabel.lineBreakMode];
self.testLabel.frame = CGRectMake(
self.testLabel.frame.origin.x, self.testLabel.frame.origin.y,
labelSize.width, labelSize.height);

Resources