I have a split view controller inside a tab bar controller. When a table row is tapped in the master view controller of split view controller, the delegate doesn't appear to trigger in the detail view controller and the 'selectedWord' value isn't passed.
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let selectedWord = wordsDisplayed[indexPath.row]
print("selectedWord in didSelectRowAt in wordsView is: \(selectedWord.languageWord)")
delegate?.wordSelected(selectedWord)
if let detailViewController = delegate as? wordsDetailView,
let detailNavigationController = detailViewController.navigationController {
splitViewController?.showDetailViewController(detailNavigationController, sender: nil)
}
}
extension wordsDetailView: WordSelectionDelegate {
func wordSelected(_ newWord: Word) {
word = newWord
print("word in WordSelectionDelegate in wordsDetailView is: \(word!.languageWord.components(separatedBy: "::")[0])")
navigationItem.title = word?.languageWord.components(separatedBy: "::")[0]
getImage()
save.isEnabled = false
clear.isEnabled = true
share.isEnabled = true
}
}
When a button is tapped in the detail view controller which depends on the selectedWord value, the program crashes at the print statement, as it unwraps an unexpected nil value:
@IBAction func save(_ sender: UIBarButtonItem) {
// Create path.
let paths = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)
print("word in save in wordsDetailView is: \(word!)")
let filePath = "\(paths[0])/\(word!.languageWord.components(separatedBy: "::")[1]).png"
print("filePath in save in DetailWord is: \(filePath)")
// Save image.
do {
try wordImage?.image?.pngData()?.write(to: URL(fileURLWithPath: filePath))
} catch {
print("Error saving image!")
}
save.isEnabled = false
}
The 'word' variable is declared at top of class as:
var word: Word? {
didSet {
refreshUI()
}
}
The print statement in didSelectRowAt is ok, but the one in the detail view controller's extension isn't (nothing prints).
I've got a simpler example that works without a tab bar controller, so I thought the introduction of the tab bar was the culprit. I've got some code in SceneDelegate.swift, that was written pre tabBarController, which handles setting up different view controllers. The 'word' variable and delegate are mentioned. I'm not sure if this needs changed to reflect the addition of another controller (tab bar), and how to go about it.
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
var window: UIWindow?
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
guard
let splitViewController = window?.rootViewController as? UISplitViewController,
let leftNavController = splitViewController.viewControllers.first as? UINavigationController,
let masterWordsController = leftNavController.viewControllers.first as? wordsView,
let detailWordController = (splitViewController.viewControllers.last as? UINavigationController)?.topViewController as? wordsDetailView
else { fatalError() }
let firstWord = masterWordsController.wordsDisplayed.first
print("firstWord in sceneWillConnectToOptions in SceneDelegate is: \(firstWord!)")
detailWordController.word = firstWord
masterWordsController.delegate = detailWordController
detailWordController.navigationItem.leftItemsSupplementBackButton = true
detailWordController.navigationItem.leftBarButtonItem = splitViewController.displayModeButtonItem
}
}