NSTextView的IBOutlet中didSet引发unrecognized selector错误求助
问题分析与解决
崩溃原因
报错信息:
Thread 1: "-[NSScrollView setFont:]: unrecognized selector sent to instance 0x14485d800"
直接说明:你代码里的reflectionForm变量实际绑定的是NSScrollView,而非预期的NSTextView。
这是因为在Interface Builder中拖入NSTextView时,系统会自动将其包裹在NSScrollView内部,你大概率误将外层的滚动视图与IBOutlet做了关联,导致后续调用setFont:方法时,给不支持该方法的NSScrollView发送消息,触发崩溃。
至于删除IBOutlet的didSet后应用能运行,是因为didSet在IBOutlet赋值时就会触发,尝试读取reflectionForm.string——NSScrollView没有string属性,此时已有潜在问题,但可能因系统容错未立刻崩溃;而保留didSet时,后续viewDidLoad里的reflectionForm.font = ...直接调用了NSScrollView不存在的方法,触发明确崩溃。
修复步骤
- 打开对应Storyboard/XIB,调出Document Outline面板(通过
Editor > Show Document Outline打开),找到文本视图层级:你会看到一个NSScrollView,其内部嵌套着真正的NSTextView(默认命名为Text View)。 - 断开错误绑定:
- 右键代码中的
reflectionForm变量,选择Delete "reflectionForm"删除旧连接; - 或在Storyboard中选中关联错误的NSScrollView,打开Connections Inspector,删除到
reflectionForm的关联项。
- 右键代码中的
- 重新绑定正确的NSTextView:
在Document Outline中选中内部的NSTextView,按住Control键拖动到代码里的@IBOutlet var reflectionForm: NSTextView!行,完成绑定。 - 验证运行:
此时viewDidLoad中的字体设置会正确作用于NSTextView,didSet里读取string也不会出现问题。
额外优化建议
- 若需实时监听文本内容变化,不要仅在
didSet中读取一次初始值,给NSTextView添加NSTextStorageDelegate监听文本变更更可靠。 - 全屏窗口代码可简化,无需先设置原点再执行zoom操作:
DispatchQueue.main.async { guard let mainScreen = NSScreen.screens.first else { return } self.view.window?.setFrame(mainScreen.frame, display: true) self.view.window?.level = .floating self.view.window?.isMovable = false self.view.window?.styleMask.remove(.resizable) self.view.window?.makeKeyAndOrderFront(nil) }
内容的提问来源于stack exchange,提问作者user8460166
相关产品推荐
相关产品推荐

