17

I am creating a reader app using UITextView and NSAttributedString, I need to split whole attributedString into smaller amount of attributed string to enable Pages Concept.

I have method for calculating frame size of given attributed string.

        CGRect rect = [attrString boundingRectWithSize:CGSizeMake(768, 10000) options:NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading context:nil];

But I need to get attributeString for (768, 1024) ContentSize.

I have used this, but the attributedStrings are not correctly divided, because it contains NSTextAttachment and HTML stings.

CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString((CFAttributedStringRef)delegate.attributedString);

How can I calculated this? and It need to be fast and need to takes small amount of memory.

Manimaran
  • 465
  • 2
  • 10

3 Answers3

7

If you want to know the size of a UITextView you should not ask the bounding rect of text, because it is not the size of the view. UITextView contains padding and you need to take into account that.
The best and easier way, is to call sizeToFit on the text view right after you added the text. Later just ask for the UItextView frame.

Andrea
  • 26,120
  • 10
  • 85
  • 131
  • Actually I have larger text with attributed text, html tables and NSTextAttachment. I want to split the text into multiple small texts (Which fit into 768X1024 frame size), so how can I split the text? – Manimaran Apr 17 '15 at 08:05
  • I think you should update the title of your question. I never had a chance to deal with a similar problem. Probably you have to dig into CoreText or if you deploy >= iOS7 try to use TextKit and NSLayoutManager, here a starting point http://www.objc.io/issue-5/getting-to-know-textkit.html . Bounding rect with size will always give an approximate evaluation of the size of the Text View. – Andrea Apr 17 '15 at 08:24
  • I have changed my title. In the link you given they are not deal with my problem – Manimaran Apr 17 '15 at 08:28
2

You can use UITextView function sizeThatFits:

[textView sizeThatFits:CGSizeMake(768, 1024)]
Vitalii Gozhenko
  • 9,220
  • 2
  • 48
  • 66
2

If you want to split text between « pages », then you need to use the capabilities of the NSLayoutManager and the NSTextContainer classes. Basically, you need to create a NSTextContainer instance for every page you wish to display, using the initWithSize: initializer. Then you register those containers using -[NSLayoutManager addTextContainer:].

Here is the relevant documentation : https://developer.apple.com/library/ios/documentation/StringsTextFonts/Conceptual/TextAndWebiPhoneOS/CustomTextProcessing/CustomTextProcessing.html#//apple_ref/doc/uid/TP40009542-CH4-SW35

Dalzhim
  • 1,970
  • 1
  • 17
  • 34
  • I have tried this, it takes tooo long time and it increases the memory also. Because I have very large document – Manimaran Apr 20 '15 at 05:56
  • Well then I guess you are stuck using the CoreText API while compensating for the attachments somehow. Or, depending on how you want to present your UI, you need to use lazy algorithms and reuse existing views. – Dalzhim Apr 20 '15 at 06:19
  • I am reusing the existing Views (`UITextView`) and I have `NSAttributedString` from a long document. It Consists of Images (`NSTextAttachment` and `HTML` Tables). Currently I am dividing attributedString into multiple pages which have size of 768X1024 using `CTFramesetterCreateWithAttributedString` but it doesn't give exact output (Gives more spaces and trimmed the texts) – Manimaran Apr 20 '15 at 07:24
  • CoreText doesn't handle attributes such as BaselineOffset, attachments and linkAttributes. If you have configured your UITextView to have a specific dictionary of attributes for links, then you need to insert those attributes into the attributedString you evaluate with CoreText otherwise the measurements can differ. – Dalzhim Apr 20 '15 at 18:39