为了将另一个问题分解为更小的部分,我尝试设置所有TextKit组件。但是,更改初始化方法后,我崩溃了NSTextStorage。出于测试目的,我将该项目简化为以下内容:
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。
enumerateLineFragmentsForGlyphRange
如果我更换
let textStorage = NSTextStorage(string: "This is a test") layoutManager.textStorage = textStorage
有了这个
layoutManager.textStorage = textView.textStorage
然后就可以了。我究竟做错了什么?
看来,做事的方法是将NSLayoutManager添加到NSTextStorage对象(使用addLayoutManager:),而不是在布局管理器上设置textStorage属性。
从苹果的文件:
将NSLayoutManager添加到NSTextStorage对象时,将自动调用此方法。您永远不需要直接调用它,但是您可能想覆盖它。如果要将NSTextStorage对象替换为一组已建立的包含接收者的文本系统对象,请使用replaceTextStorage:。
链接到setTextStorage:用于NSLayoutManager
大概是在’addLayoutManager:’中完成了某些事情,而在setTextStorage中没有完成,导致崩溃。
如果viewDidLoad完成后似乎已将其清除,则可能还需要增加textStorage变量的范围。