Append text to NSScrollView - Thread 1: Fatal error: Unexpectedly found nil while unwrapping an Optional value
Append text to NSScrollView - Thread 1: Fatal error: Unexpectedly found nil while unwrapping an Optional value
我正在做一个 Mac 应用程序,当我从另一个 class 调用函数时,我在将文本附加到 NSScrollView 时遇到问题。
我的 ViewController class:
上有这个功能
import Cocoa
class PopoverVC1: NSViewController {
let popover1 = NSPopover()
class func loadView() ->PopoverVC1 {
let vc = NSStoryboard(name: NSStoryboard.Name(rawValue: "Main"),
bundle: nil).instantiateController(withIdentifier:
NSStoryboard.SceneIdentifier(rawValue: "Popover1")) as! PopoverVC1
vc.popover1.contentViewController = vc
return vc
}
override func viewDidLoad() {
super.viewDidLoad()
popover1.behavior = .transient
popover1.contentViewController = self
}
func showPopover (view: NSView){
popover1.show(relativeTo: view.bounds, of: view, preferredEdge: .maxY)
}
@IBOutlet weak var radioOption1: NSButton!
@IBOutlet weak var radioOption2: NSButton!
@IBOutlet weak var radioOption3: NSButton!
@IBAction func clickOption(_ sender: NSButton) {
switch sender {
case radioOption1: popover1.performClose(sender)
case radioOption2: let vc = ViewController()
vc.myPrint(string: "This is a test")
default: print ("hello")
}
}
}
比起我有一个 PopoverVC1 class,这是一个 class 我正在使用的弹出窗口:
import Cocoa
class ViewController: NSViewController {
@IBOutlet weak var oneYes: NSButton!
@IBOutlet weak var oneNo: NSButton!
@IBOutlet weak var notesArea: NSScrollView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override var representedObject: Any? {
didSet {
// Update the view, if already loaded
}
}
func myPrint (string: String){
let mystring = string
let myNotes = notesArea.documentView as? NSTextView
let text = myNotes?.textStorage!
let attr = NSAttributedString(string: mystring)
text?.append(attr)
}
let popover1 = NSPopover()
@IBAction func oneClicked(_ sender: NSButton) {
switch sender {
case oneYes: let vc = PopoverVC1.loadView()
vc.showPopover(view: sender)
case oneNo:
let myNotes = notesArea.documentView as? NSTextView
let text = myNotes?.textStorage!
let attr = NSAttributedString(string: "test")
text?.append(attr)
default: print ("")
}
}
}
但是,当我按下应该调用函数 "myPrint" 并传递参数的单选按钮 "oneNo" 时出现错误。
线程 1:致命错误:在展开可选值时意外发现 nil
我做了一些测试,当我从 ViewCotroller class 中调用相同的函数 "myPrint" 时,它工作正常。
有什么想法吗?
您的问题在 clickOption
中,当您致电时:
let vc = ViewController()
vc.myPrint(string: "This is a test")
当您从代码中调用此方法并且 ViewController's
UIViews
在故事板中设置时,不会建立与故事板的连接。这就是为什么当您调用函数 myPrint
时 notesArea
为 nil 的原因。在这种情况下,您正在创建 ViewController
的新副本,它不会与创建弹出窗口的副本相同。
有几种方法可以解决您要解决的问题。其中之一被称为 delegate
。这是一种调用 ViewController's
方法的方法,就像您 popover
继承它们一样。您可以查看教程 here。我们的想法是,我们希望在您的 popover
中引用 ViewController
,以便您可以调用 protocol
中的函数。那么符合protocol
的ViewController
将负责处理方法调用。
所以让我们创建一个名为 PrintableDelegate
的 protocol
并让您的 ViewController
class 符合它。然后在你的 popover
中,你将能够将 ViewController
作为一个名为 delegate
的 weak var
引用(你可以使用任何你想要的名称,但 delegate
是标准的)。然后我们可以通过简单地写delegate?.myPrint(string: "Test")
来调用协议PrintableDelegate
中描述的方法。我已经从我的示例中删除了一些与您无关的代码。
protocol PrintableDelegate {
func myPrint(string: String)
}
class ViewController : UIViewController, PrintableDelegate {
func myPrint (string: String){
let mystring = string
let myNotes = notesArea.documentView as? NSTextView
let text = myNotes?.textStorage!
let attr = NSAttributedString(string: mystring)
text?.append(attr)
}
@IBAction func oneClicked(_ sender: NSButton) {
let vc = PopoverVC1.loadView()
// Set the delegate of the popover to this ViewController
vc.delegate = self
vc.showPopover(view: sender)
}
}
class PopoverVC1: NSViewController {
// Delegates should be weak to avoid a retain cycle
weak var delegate: PrintableDelegate?
@IBAction func clickOption(_ sender: NSButton) {
// Use the delegate that was set by the ViewController
// Note that it is optional so if it was not set, then this will do nothing
delegate?.myPrint(string: "This is a test")
}
}
我正在做一个 Mac 应用程序,当我从另一个 class 调用函数时,我在将文本附加到 NSScrollView 时遇到问题。
我的 ViewController class:
上有这个功能import Cocoa
class PopoverVC1: NSViewController {
let popover1 = NSPopover()
class func loadView() ->PopoverVC1 {
let vc = NSStoryboard(name: NSStoryboard.Name(rawValue: "Main"),
bundle: nil).instantiateController(withIdentifier:
NSStoryboard.SceneIdentifier(rawValue: "Popover1")) as! PopoverVC1
vc.popover1.contentViewController = vc
return vc
}
override func viewDidLoad() {
super.viewDidLoad()
popover1.behavior = .transient
popover1.contentViewController = self
}
func showPopover (view: NSView){
popover1.show(relativeTo: view.bounds, of: view, preferredEdge: .maxY)
}
@IBOutlet weak var radioOption1: NSButton!
@IBOutlet weak var radioOption2: NSButton!
@IBOutlet weak var radioOption3: NSButton!
@IBAction func clickOption(_ sender: NSButton) {
switch sender {
case radioOption1: popover1.performClose(sender)
case radioOption2: let vc = ViewController()
vc.myPrint(string: "This is a test")
default: print ("hello")
}
}
}
比起我有一个 PopoverVC1 class,这是一个 class 我正在使用的弹出窗口:
import Cocoa
class ViewController: NSViewController {
@IBOutlet weak var oneYes: NSButton!
@IBOutlet weak var oneNo: NSButton!
@IBOutlet weak var notesArea: NSScrollView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override var representedObject: Any? {
didSet {
// Update the view, if already loaded
}
}
func myPrint (string: String){
let mystring = string
let myNotes = notesArea.documentView as? NSTextView
let text = myNotes?.textStorage!
let attr = NSAttributedString(string: mystring)
text?.append(attr)
}
let popover1 = NSPopover()
@IBAction func oneClicked(_ sender: NSButton) {
switch sender {
case oneYes: let vc = PopoverVC1.loadView()
vc.showPopover(view: sender)
case oneNo:
let myNotes = notesArea.documentView as? NSTextView
let text = myNotes?.textStorage!
let attr = NSAttributedString(string: "test")
text?.append(attr)
default: print ("")
}
}
}
但是,当我按下应该调用函数 "myPrint" 并传递参数的单选按钮 "oneNo" 时出现错误。
线程 1:致命错误:在展开可选值时意外发现 nil
我做了一些测试,当我从 ViewCotroller class 中调用相同的函数 "myPrint" 时,它工作正常。
有什么想法吗?
您的问题在 clickOption
中,当您致电时:
let vc = ViewController()
vc.myPrint(string: "This is a test")
当您从代码中调用此方法并且 ViewController's
UIViews
在故事板中设置时,不会建立与故事板的连接。这就是为什么当您调用函数 myPrint
时 notesArea
为 nil 的原因。在这种情况下,您正在创建 ViewController
的新副本,它不会与创建弹出窗口的副本相同。
有几种方法可以解决您要解决的问题。其中之一被称为 delegate
。这是一种调用 ViewController's
方法的方法,就像您 popover
继承它们一样。您可以查看教程 here。我们的想法是,我们希望在您的 popover
中引用 ViewController
,以便您可以调用 protocol
中的函数。那么符合protocol
的ViewController
将负责处理方法调用。
所以让我们创建一个名为 PrintableDelegate
的 protocol
并让您的 ViewController
class 符合它。然后在你的 popover
中,你将能够将 ViewController
作为一个名为 delegate
的 weak var
引用(你可以使用任何你想要的名称,但 delegate
是标准的)。然后我们可以通过简单地写delegate?.myPrint(string: "Test")
来调用协议PrintableDelegate
中描述的方法。我已经从我的示例中删除了一些与您无关的代码。
protocol PrintableDelegate {
func myPrint(string: String)
}
class ViewController : UIViewController, PrintableDelegate {
func myPrint (string: String){
let mystring = string
let myNotes = notesArea.documentView as? NSTextView
let text = myNotes?.textStorage!
let attr = NSAttributedString(string: mystring)
text?.append(attr)
}
@IBAction func oneClicked(_ sender: NSButton) {
let vc = PopoverVC1.loadView()
// Set the delegate of the popover to this ViewController
vc.delegate = self
vc.showPopover(view: sender)
}
}
class PopoverVC1: NSViewController {
// Delegates should be weak to avoid a retain cycle
weak var delegate: PrintableDelegate?
@IBAction func clickOption(_ sender: NSButton) {
// Use the delegate that was set by the ViewController
// Note that it is optional so if it was not set, then this will do nothing
delegate?.myPrint(string: "This is a test")
}
}