Как инициализировать NSTextStorage с помощью строки в Swift
Чтобы разбить другую проблему на более мелкие части, я пытаюсь настроить все компоненты TextKit. Тем не менее, я получаю сбой после изменения способа инициализации NSTextStorage
, В целях тестирования я упростил проект до следующего:
import UIKit
class ViewController3: UIViewController {
@IBOutlet weak var textView: UITextView!
@IBOutlet weak var myTextView: MyTextView!
override func viewDidLoad() {
super.viewDidLoad()
let container = NSTextContainer(size: myTextView.bounds.size)
let layoutManager = NSLayoutManager()
let textStorage = NSTextStorage(string: "This is a test")
layoutManager.addTextContainer(container)
//layoutManager.textStorage = textView.textStorage // This works
layoutManager.textStorage = textStorage // This doesn't work
myTextView.layoutManager = layoutManager
}
}
class MyTextView: UIView {
var layoutManager: NSLayoutManager?
override func drawRect(rect: CGRect) {
let context = UIGraphicsGetCurrentContext();
// Enumerate all the line fragments in the text
layoutManager?.enumerateLineFragmentsForGlyphRange(NSMakeRange(0, layoutManager!.numberOfGlyphs), usingBlock: {
(lineRect: CGRect, usedRect: CGRect, textContainer: NSTextContainer!, glyphRange: NSRange, stop: UnsafeMutablePointer<ObjCBool>) -> Void in
// Draw the line fragment
self.layoutManager?.drawGlyphsForGlyphRange(glyphRange, atPoint: CGPointMake(0, 0))
})
}
}
Он падает на enumerateLineFragmentsForGlyphRange
с кодом исключения EXC_I386_GPFLT. Этот код не очень объяснительный. Основная проблема, кажется, сводится к тому, как я инициализирую NSTextStorage
,
Если я заменю
let textStorage = NSTextStorage(string: "This is a test")
layoutManager.textStorage = textStorage
с этим
layoutManager.textStorage = textView.textStorage
тогда это работает. Что я делаю неправильно?
1 ответ
Кажется, что способ сделать что-то, это добавить NSLayoutManager к объекту NSTextStorage (используя addLayoutManager:), а не устанавливать свойство textStorage в менеджере макета.
Из документов Apple:
Этот метод вызывается автоматически при добавлении NSLayoutManager в объект NSTextStorage; вам никогда не нужно вызывать его напрямую, но вы можете переопределить его. Если вы хотите заменить объект NSTextStorage для установленной группы объектов текстовой системы, содержащей получателя, используйте replaceTextStorage:.
Ссылка на setTextStorage: для NSLayoutManager
Предположительно что-то делается в addLayoutManager: что не делается в setTextStorage, вызывая сбой.
Вы можете также захотеть увеличить область действия переменной textStorage, если кажется, что она очищается после завершения viewDidLoad.