在 swift for macOS 中使用委托将数据传递到主视图控制器
Passing data to main view controller with delegate in swift for macOS
我有一个主视图控制器 ViewController
和一个辅助视图控制器:AddBookSheetViewController
。第二个视图控制器显示为 sheet 并且应该提供由于用户输入标识符而抓取网站的功能,随后将处理后的数据返回给 ViewController.
我找到了这个相关的答案,它反向描述了我的问题,因此看起来很有希望。我应该可以从那里继续,对吧?
Passing data from a ViewController to a TabViewController
唉,数据没有得到传递。这是我的代码:
@objc protocol AddBookSheetViewControllerDelegate {
func addBookFromExtern(sender: AddBookSheetViewController, data: [String])
}
class AddBookSheetViewController: NSViewController {
weak var delegate: AddBookSheetViewControllerDelegate?
@IBOutlet weak var isbnSheetTextField: NSTextField!
var bibTex = "" {
didSet {
//: sets as expected
print(oldValue, "replaced for new:", bibTex)
let bookFromBibtex = BookFromBibtex()
let texData = bookFromBibtex.getInfo(bibtex: bibTex)
//: prints
print("now we've reached delegate")
//: nothing happens on the other side
self.delegate?.addBookFromExtern(sender: self, data: texData)
//: prints
print("now we've passed delegate")
}
}
override func viewDidLoad() {
super.viewDidLoad()
//
//: might this be problem? "parent"?
//
if let viewController = parent as? ViewController {
self.delegate = viewController
}
}
@IBAction func getBookSheetButton(_ sender: Any) {
if isbnSheetTextField.stringValue != "" {
//: .letterCount is a String extension
if isbnSheetTextField.stringValue.letterCount <= 0 {
//: scrape() does the URLSession and regex work
scrape(isbn: isbnSheetTextField.stringValue)
//: cont'd in bibTex didSet
} else { print("Unvalid ISBN.")}
} else {print ("Enter ISBN.") }
}
}
class ViewController: NSViewController, NSWindowDelegate, AddBookSheetViewControllerDelegate {
func addBookFromExtern(sender: AddBookSheetViewController, data: [String]) {
let newBook = Book(author: data[0], title: data[1], lentBy: "", signature: "", comment: "", isbn: "123", lentDate: "", creationDate: Date())
self.BookArrayController.addObject(newBook)
print("signal received") //: doesn't get triggered
}
}
其他人建议的不同方法,例如here,但它们似乎是 iOS 特定的,或者我无法实现它们。
你能找出问题所在吗? (也许在 AddBookSheetViewController
s viewDidLoad()
函数中,也许特别与标识符“parent”有关?)谢谢!
-- 编辑
回答
@vadian 给出了关键的见解,当然也提供了一个更优雅的解决方案。最好使用他的答案。在当前设置中,这有效:
override func viewDidLoad() {
super.viewDidLoad()
//: or presentingViewController
if let viewController = presenting as? ViewController {
self.delegate = viewController
}
}
这也有效:
override func viewDidLoad() {
super.viewDidLoad()
let mainViewController = presenting as! ViewController
self.delegate = mainViewController
}
}
但是,这会导致主要 vc ViewController 的 NSTableView(数据部署到的位置)出现一些故障。
加法
/ ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** /
诺塔贝内:
根据@vadian 的说法,以下是特别糟糕的做法,即错误的,以至于他建议我将其完全删除。我会把它留作教育目的。
/ ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** * * ** ** ** ** ** /
就在@vadian 的回答之前,我在阅读这篇文章后尝试了一些成功:macOS Swift master-detail delegate/protocol not working
也就是说,我能够传递到主要 vc ViewController,但应用程序因意外的 nil 而崩溃。 (我没弄明白为什么)。将 AddBookSheetViewControllerDelegate
替换为 ViewController
会产生相同的行为..
override func viewDidLoad() {
super.viewDidLoad()
let mainViewController = ViewController()
if let viewController = mainViewController as? AddBookSheetViewControllerDelegate {
self.delegate = viewController
}
}
问题的发生很可能是因为 didSet
比 viewDidLoad
调用得早
但是在这种情况下你根本不需要协议/委托。
由于 AddBook 控制器以模态方式呈现,因此使用 属性 presentingViewController
.
委托方法中的sender
参数未使用。
let parent = presentingViewController as! ViewController
parent.addBook(_ data: [String])
我什至会在添加控制器中创建图书 return
parent.addBook(_ book: Book)
我有一个主视图控制器 ViewController
和一个辅助视图控制器:AddBookSheetViewController
。第二个视图控制器显示为 sheet 并且应该提供由于用户输入标识符而抓取网站的功能,随后将处理后的数据返回给 ViewController.
我找到了这个相关的答案,它反向描述了我的问题,因此看起来很有希望。我应该可以从那里继续,对吧? Passing data from a ViewController to a TabViewController
唉,数据没有得到传递。这是我的代码:
@objc protocol AddBookSheetViewControllerDelegate {
func addBookFromExtern(sender: AddBookSheetViewController, data: [String])
}
class AddBookSheetViewController: NSViewController {
weak var delegate: AddBookSheetViewControllerDelegate?
@IBOutlet weak var isbnSheetTextField: NSTextField!
var bibTex = "" {
didSet {
//: sets as expected
print(oldValue, "replaced for new:", bibTex)
let bookFromBibtex = BookFromBibtex()
let texData = bookFromBibtex.getInfo(bibtex: bibTex)
//: prints
print("now we've reached delegate")
//: nothing happens on the other side
self.delegate?.addBookFromExtern(sender: self, data: texData)
//: prints
print("now we've passed delegate")
}
}
override func viewDidLoad() {
super.viewDidLoad()
//
//: might this be problem? "parent"?
//
if let viewController = parent as? ViewController {
self.delegate = viewController
}
}
@IBAction func getBookSheetButton(_ sender: Any) {
if isbnSheetTextField.stringValue != "" {
//: .letterCount is a String extension
if isbnSheetTextField.stringValue.letterCount <= 0 {
//: scrape() does the URLSession and regex work
scrape(isbn: isbnSheetTextField.stringValue)
//: cont'd in bibTex didSet
} else { print("Unvalid ISBN.")}
} else {print ("Enter ISBN.") }
}
}
class ViewController: NSViewController, NSWindowDelegate, AddBookSheetViewControllerDelegate {
func addBookFromExtern(sender: AddBookSheetViewController, data: [String]) {
let newBook = Book(author: data[0], title: data[1], lentBy: "", signature: "", comment: "", isbn: "123", lentDate: "", creationDate: Date())
self.BookArrayController.addObject(newBook)
print("signal received") //: doesn't get triggered
}
}
其他人建议的不同方法,例如here,但它们似乎是 iOS 特定的,或者我无法实现它们。
你能找出问题所在吗? (也许在 AddBookSheetViewController
s viewDidLoad()
函数中,也许特别与标识符“parent”有关?)谢谢!
-- 编辑
回答
@vadian 给出了关键的见解,当然也提供了一个更优雅的解决方案。最好使用他的答案。在当前设置中,这有效:
override func viewDidLoad() {
super.viewDidLoad()
//: or presentingViewController
if let viewController = presenting as? ViewController {
self.delegate = viewController
}
}
这也有效:
override func viewDidLoad() {
super.viewDidLoad()
let mainViewController = presenting as! ViewController
self.delegate = mainViewController
}
}
但是,这会导致主要 vc ViewController 的 NSTableView(数据部署到的位置)出现一些故障。
加法
/ ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** /
诺塔贝内:
根据@vadian 的说法,以下是特别糟糕的做法,即错误的,以至于他建议我将其完全删除。我会把它留作教育目的。
/ ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** * * ** ** ** ** ** /
就在@vadian 的回答之前,我在阅读这篇文章后尝试了一些成功:macOS Swift master-detail delegate/protocol not working
也就是说,我能够传递到主要 vc ViewController,但应用程序因意外的 nil 而崩溃。 (我没弄明白为什么)。将 AddBookSheetViewControllerDelegate
替换为 ViewController
会产生相同的行为..
override func viewDidLoad() {
super.viewDidLoad()
let mainViewController = ViewController()
if let viewController = mainViewController as? AddBookSheetViewControllerDelegate {
self.delegate = viewController
}
}
问题的发生很可能是因为 didSet
比 viewDidLoad
但是在这种情况下你根本不需要协议/委托。
由于 AddBook 控制器以模态方式呈现,因此使用 属性 presentingViewController
.
委托方法中的sender
参数未使用。
let parent = presentingViewController as! ViewController
parent.addBook(_ data: [String])
我什至会在添加控制器中创建图书 return
parent.addBook(_ book: Book)