为了将another problem分解成更小的部分,我正在尝试设置所有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
然后它的工作原理。我做错了什么?
答案 0 :(得分:7)
似乎做事的方法是将NSLayoutManager添加到NSTextStorage对象,(使用addLayoutManager :)而不是在布局管理器上设置textStorage属性。
来自Apple的文件:
将NSLayoutManager添加到NSTextStorage对象时,会自动调用此方法;你永远不需要直接调用它,但你可能想要覆盖它。如果要为包含接收器的已建立的文本系统对象组替换NSTextStorage对象,请使用replaceTextStorage:。
Link to setTextStorage: for NSLayoutManager
据推测,有些事情是在'addLayoutManager:'中完成的,这在setTextStorage中无法完成,导致崩溃。
你可能还想增加textStorage变量的范围,如果它看起来在viewDidLoad完成后被清除了。