I have a long text (multiple screen pages) stored in an NSTextStorage. I instantiate an NSLayoutManager() and add the textStorage to it. Then I keep adding NSTextContainers of specific size until I use up the whole text. The containers are also added to an array. The idea is that this gets only calculated once so I can later only work with the containers (pages).
This is all part of a model class, which is instantiated in the UIPageViewController. UIPageViewController presents ViewControllers that contain only a UITextView and has a reference to the model. UITextView gets instantiated using an NSTextContainer from an array described above.
This all works well, the problem is, it only works once. Once I "turn" a page, the other page is blank. When I am in landscape, I get two ViewControllers and they both load up correctly. Again, once I turn a page, the textView is empty.
It works perfectly when I create new NSTextStorage, NSLayoutManager and the NSTextContainers every time the page is turned, however, that`s awefully slow and inefficient.
Any idea what could be the cause?
EDIT:
This is creating the textView on a page created by UIPageViewController:
func reloadData() {
let rect = CGRect(
x: view.bounds.origin.x + spacing,
y: view.bounds.origin.y + spacing,
width: view.bounds.width - spacing * 2,
height: view.bounds.height - spacing * 2)
if let textContainer = bookReader.getPage(pageIndex, frame: rect) {
textView = UITextView(frame: rect, textContainer: textContainer)
textView!.textAlignment = textAlignment
textView!.editable = false
lastSize = textView!.frame
view.addSubview(textView!)
} else {
print("did't get a page")
}
}
And this is in the model instantiated by the UIPageViewController, called by the code above:
func getPage(page: Int, frame: CGRect) -> NSTextContainer? {
// if the screen size was changed (rotated) erase everything
if self.lastFrame != frame {
print("size was changed")
chapters.removeAll()
self.lastFrame = frame
}
// if the data has been already calculated
if chapters.count > 0 {
// find chapter and page (this part is not working correctly yet but that doesn`t really matter in this case, it just fetches wrong page in some cases)
var chapter = 0
var subPage = 0
var checkedPages = 0
for i in 0..<chapters.count {
if page - 1 < (i + 1) * chapters[i]!.count {
chapter = i
subPage = page - 1 - checkedPages
break
} else {
checkedPages += chapters[i]!.count
}
}
print("desired page: \(page) - chapter: \(chapter), page: \(subPage)")
// return textContainer
if let textContainer = chapters[chapter]?[subPage] {
print("the container is in the array")
return textContainer
} else {
print("page couldn't been found")
return nil
}
} else {
// calculate the whole book
numberOfPages = 0
for (index, url) in htmls.enumerate() {
let data = NSData(contentsOfURL: url)
let attributedString = NSAttributedString(HTMLData: data, options: options, documentAttributes: nil)
let textStorage = NSTextStorage(attributedString: attributedString)
let layoutManager = NSLayoutManager()
textStorage.addLayoutManager(layoutManager)
var i = 0
while layoutManager.textContainerForGlyphAtIndex(textStorage.length - 1, effectiveRange: nil) == nil {
let textContainer = NSTextContainer(size: frame.size)
layoutManager.addTextContainer(textContainer)
if chapters[index] != nil {
chapters[index]![i] = textContainer
} else {
chapters[index] = [i:textContainer]
}
i++
}
numberOfPages += i - 1
print("chapter \(index) count \(chapters[index]!.count)")
}
}
print("recursive call, number of pages: \(numberOfPages)")
return getPage(page, frame: frame)
}