Let's suppose you are using TextKit to layout your text, i.e. the combination of NSTextStorage, NSLayoutManager and NSTextContainer, combined with UITextView. And let's also suppose that you'll be using Auto Layout to anchor a UIPageViewController's view to the views it will be sitting next to (or perhaps be using it within a UIStackView, you brave soul!).
func textLayoutContainers(size:CGSize, scrolling:Bool, section:String, page:Int) {
var textViewArr = [UITextView]()
// Create attr string - content
guard let textString = loadHTMLData(section: section, page: page) else {return}
// Set up text storage and add string
let textStorage = NSTextStorage(attributedString: textString)
// Create a layout manager
let textLayout = NSLayoutManager()
// Add layout manager to text storage object
textStorage.addLayoutManager(textLayout)
// create text containers and views, adding each container to the layout manager
var i = 0
let textInset:CGFloat = size.width/25
let textSize = CGSize(width: size.width*0.6-textInset*2, height: size.height*0.7-textInset*2)
var glyphRange:Int
var numberOfGlyphs:Int
repeat {
// Create a text container
let textContainer = NSTextContainer(size:textSize)
// Add text container to text layout manager
textLayout.addTextContainer(textContainer)
// Instantiate UITextView object using the text container
let textView:UITextView = UITextView(frame:CGRect(x:0,y:0, width:size.width,height:size.height), textContainer:textContainer)
textView.isScrollEnabled = scrolling
textView.textContainerInset.bottom = textInset
textView.textContainerInset.left = textInset
textView.textContainerInset.right = textInset
// Give the container an identifier tag
textView.tag = i
glyphRange = NSMaxRange(textLayout.glyphRange(for: textContainer))
numberOfGlyphs = textLayout.numberOfGlyphs
textViewArr.append(textView)
i+=1
}
while (glyphRange < numberOfGlyphs-1)
textViews = textViewArr
}
Now there are a few factors that are a bit of an oddity to me. First, we need to provide a CGSize for the NSTextContainer and a frame for the UITextViews (in the form of CGRect). But those values will be adjusted by Auto Layout, so count for very little (BUT cannot be omitted, and if you make containers too small you'll be slowing your app down creating them all). Second if you choose to leave scroll enabled on your UITextViews then the view will ignore any size requirements and display all text in a single UITextView for you to scroll (no matter the dimensions of the NSTextContainer you set).
If you disable scrolling for your text views then text will be set across pages, as expected. It will also automatically handle re-layout on size changes. But it does not handle how many pages are needed or displayed, so checks need to be put into place within the UIPageViewController DataSource and Delegate methods to make sure all the text you want to show is being shown and that you are not creating blank pages.
For now these are just a few notes on the auto-magical features that get added using the TextKit/UIPageViewController/Auto Layout combo, I'm planning to return to this post with some practical code snippets.
Comments
Post a Comment