How to Get Word Wrap Information with the New iOS 7 APIs

How do I get word wrap information with the new iOS 7 APIs?

Example:

CGFloat maxWidth = 150;
NSAttributedString *s =
[[NSAttributedString alloc]
initWithString:@"The quick brown fox jumped over the lazy dog."
attributes:@{NSFontAttributeName:[UIFont fontWithName:@"GillSans" size:20]}];
NSTextContainer* tc =
[[NSTextContainer alloc] initWithSize:CGSizeMake(maxWidth,CGFLOAT_MAX)];
NSLayoutManager* lm = [NSLayoutManager new];
NSTextStorage* tm = [[NSTextStorage alloc] initWithAttributedString:s];
[tm addLayoutManager:lm];
[lm addTextContainer:tc];
[lm enumerateLineFragmentsForGlyphRange:NSMakeRange(0,lm.numberOfGlyphs)
usingBlock:^(CGRect rect, CGRect usedRect,
NSTextContainer *textContainer,
NSRange glyphRange, BOOL *stop) {
NSRange r = [lm characterRangeForGlyphRange:glyphRange actualGlyphRange:nil];
NSLog(@"%@", [s.string substringWithRange:r]);
}];

UITextView : get text with wrap info

See my answer here:

https://stackoverflow.com/a/13588322/341994

What you are asking to do is exactly what Core Text does for you. Indeed, Core Text is how UITextView knows how to wrap text. So you can ask Core Text where the line breaks are, just as UITextView does. See the example code in my answer - it's a lot simpler and more reliable than what you're trying to do.

How to wrap text around attachments using iOS7 Text Kit?

NSTextAttachments are treated as a single character by NSAttributedString. So, in order to adjust their alignment you must do so as you would for text. It took me hours of fiddling with attachment.bounds (which I never could get to work properly) to finally figure this out. Here's an example of how to horizontally align an NSTextAttachment.

#def BETWEEN_SECTION_SPACING 10  

// creates a text attachment with an image

NSTextAttachment *attachment = [[NSTextAttachment alloc] init];

attachment.image = [UIImage imageNamed:@"sample_image.jpg"];

NSMutableAttributedString *imageAttrString = [[NSAttributedString attributedStringWithAttachment:attachment] mutableCopy];

// sets the paragraph styling of the text attachment

NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init] ;

[paragraphStyle setAlignment:NSTextAlignmentCenter]; // centers image horizontally

[paragraphStyle setParagraphSpacing:BETWEEN_SECTION_SPACING]; // adds some padding between the image and the following section

[imageAttrString addAttribute:NSParagraphStyleAttributeName value:paragraphStyle range:NSMakeRange(0, [imageAttrString length])];

After this, you would append imageAttrString to an existing attributed string and perhaps append another after it. One quirk is that because the attachment is a character it is not treated as its own paragraph. In order for that to be the case you will need to surround it with \n (newline characters). Just append these to both sides of the attachment's attributed string.

Hope that helps, it took me ages to figure out.

How to word wrap text in annotation subtitle

AFAIK it can't be done. Setting left/right button text is space-limited indeed. Seems the only solution is to addObserver and roll your own animated views entirely.

NSLineBreakByCharWrapping not working in iOS7

I think it's a bug in iOS 7. We have a couple of apps where we accidentally used NSLineBreakCharWrapping, and it just did word wrapping which was what we intended... and they are all of a sudden broken on iOS 8.. it wasn't fixed until iOS 8 probably most of the time wrap by word is used and nobody realized it.

boundingRectWithSize does not respect word wrapping

Did some more research and ended up finding this.

CGSize textSize = [textView sizeThatFits:CGSizeMake(textView.frame.size.width, FLT_MAX)];
CGFloat textHeight = textSize.height;

Hope this helps someone out there!

Return a word-wrapped NSString from a longer NSString

There really is no need to reinvent this wheel, since it is exactly what the text engine does for you every time you wrap text. And what is the text engine? It is Core Text. If you drop down to the level of Core Text and have a CTFramesetter lay out the text for you, you can learn where it is putting the line breaks by asking for the resulting CTLines.

The documentation will get you started:

http://developer.apple.com/library/ios/#documentation/StringsTextFonts/Conceptual/CoreText_Programming/Operations/Operations.html

And there are lots of good tutorials on the Web.

Simple example:

NSString* s = @"Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do "
@"eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut "
@"enim ad minim veniam, quis nostrud exercitation ullamco laboris "
@"nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor "
@"in reprehenderit in voluptate velit esse cillum dolore eu fugiat "
@"nulla pariatur. Excepteur sint occaecat cupidatat non proident, "
@"sunt in culpa qui officia deserunt mollit.";
NSAttributedString* text = [[NSAttributedString alloc] initWithString:s];

CTFramesetterRef fs =
CTFramesetterCreateWithAttributedString((__bridge CFAttributedStringRef)text);
CGMutablePathRef path = CGPathCreateMutable();
CGPathAddRect(path, NULL, CGRectMake(0,0,200,100000));
CTFrameRef f = CTFramesetterCreateFrame(fs, CFRangeMake(0, 0), path, NULL);
CTFrameDraw(f, NULL);

NSArray* lines = (__bridge NSArray*)CTFrameGetLines(f);
for (id aLine in lines) {
CTLineRef theLine = (__bridge CTLineRef)aLine;
CFRange range = CTLineGetStringRange(theLine);
NSLog(@"%ld %ld", range.location, range.length);
}
CGPathRelease(path);
CFRelease(f);
CFRelease(fs);

As you will see, the output shows the range of each line of wrapped text. Isn't this the sort of thing you're after?

UILabel wrong word wrap in iOS 11

This is a change by Apple to prevent widowed lines. From a design perspective, it is preferred to avoid having a single word on a line of text. UILabel now breaks the line in a way that the second line of text always has at least 2 words on it.

See the answer below for an option to disable it.

Sample Image

Also here's a good article about "widowed" and "orphaned" text.



Related Topics



Leave a reply



Submit