Как инициализировать 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.

Другие вопросы по тегам