I have a main view controller ViewController
and a secondary one: AddBookSheetViewController
. The second view controller is presented as a sheet and is supposed to provide the function of scraping a website due to an user input identifier and subsequently yield the processed data back to the ViewController.
I found this related answer, which describes my problem in reverse and thus looks promising. I should be able to go on from there, right? Passing data from a ViewController to a TabViewController
Alas, the data doesn't get passed on. Here's my code:
@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
}
}
Other's suggested different methods, e.g. here, but they seem to be either iOS specific or I was unable to implement them.
Can you identify the problem? (Perhaps in the AddBookSheetViewController
s viewDidLoad()
function and perhaps specifically pertaining to the identifier ´parent`?) Thanks!
-- Edit
Answer
@vadian gave the crucial insight and certainly a more elegant solution altogether. Best to use his answer. In the current setup this works:
override func viewDidLoad() {
super.viewDidLoad()
//: or presentingViewController
if let viewController = presenting as? ViewController {
self.delegate = viewController
}
}
this also works:
override func viewDidLoad() {
super.viewDidLoad()
let mainViewController = presenting as! ViewController
self.delegate = mainViewController
}
}
However, this causes some glitches in the main vc ViewController's NSTableView (where the data is deployed to).
Addition
/ ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** /
Nota Bene:
According to @vadian, the following is particularly bad practice, i.e. wrong and is so much so that he suggested, I deleted it altogether. I'll leave it for educational purposes.
/ ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** /
Just prior to @vadian's answer I had some semi success trying it like this after reading this: macOS Swift master-detail delegate/protocol not working
That is, I was able to pass over to the main vc ViewController, but the app crashed with unexpected nil. (I didn't figure out why). Replacing AddBookSheetViewControllerDelegate
with ViewController
yielded the same behavior..
override func viewDidLoad() {
super.viewDidLoad()
let mainViewController = ViewController()
if let viewController = mainViewController as? AddBookSheetViewControllerDelegate {
self.delegate = viewController
}
}