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