How to Initialize NSTextStorage with a String in Swift

霸气de小男生 提交于 2019-11-28 04:08:48

问题


In order to break another problem down into smaller parts, I am trying to set up all the TextKit components. However, I am getting an crash after changing how I initialize NSTextStorage. For testing purposes I have simplified the project to the following:

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))

        })
    }
}

It crashes at enumerateLineFragmentsForGlyphRange with an exception code of EXC_I386_GPFLT. That code isn't very explanitory. The basic problem seems to be coming down to how I am initializing NSTextStorage.

If I replace

let textStorage = NSTextStorage(string: "This is a test")
layoutManager.textStorage = textStorage

with this

layoutManager.textStorage = textView.textStorage

then it works. What am I doing wrong?


回答1:


It seems the way to do things, is to add the NSLayoutManager to the NSTextStorage object, (using addLayoutManager:) rather than setting the textStorage property on the layout manager.

From Apple's documents:

This method is invoked automatically when you add an NSLayoutManager to an NSTextStorage object; you should never need to invoke it directly, but you might want to override it. If you want to replace the NSTextStorage object for an established group of text-system objects containing the receiver, use replaceTextStorage:.

Link to setTextStorage: for NSLayoutManager

Presumably something gets done in 'addLayoutManager:' which doesn't get done in setTextStorage, causing the crash.

You might also want to increase the scope of the textStorage variable, if it appears that it's getting cleared up once viewDidLoad finish.



来源:https://stackoverflow.com/questions/30796174/how-to-initialize-nstextstorage-with-a-string-in-swift

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!