popOver pickerView value not passing to presenting controller

The pop over controller presenting controller class. The print line in loadInitialValues() shows that the pop over picker view value is not passed to this class, it is an empty value. The presenting segue is setup in interface builder, the pop over presents normally, I can select a picker view value and confirm with the done button with the pop over disappearing.


import UIKit


class WordsViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, UITabBarControllerDelegate, UIPopoverPresentationControllerDelegate, LanguagesPopOverDelegate {


@IBOutlet weak var tableView: UITableView!

@IBOutlet weak var clear: UIButton!

@IBOutlet weak var reset: UIButton!

@IBOutlet weak var sort: UIButton!

@IBOutlet weak var languagePicker: UIButton!


var words = [String]()

var tableViewWords = [String]()

var chosenWords = [String]()

var useHomework: Bool!

var languages = [String]()

var language = String()

var chosenLanguage = String()

var textField: UITextField?

let wordString = "Words"

var languagesWithWords = [String]()


override func viewDidLoad() {

super.viewDidLoad()


loadLanguages()

chosenLanguageLoad()

loadInitialValues()

print("chosenLanguage in viewDidLoad in WordsViewController is: \(chosenLanguage)")


tableView.allowsMultipleSelection = false

tableView.reloadData()

navigationItem.title = "\(chosenLanguage.capitalized) Words"

navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: .play, target: self, action: #selector(test))

navigationItem.leftBarButtonItem = UIBarButtonItem(barButtonSystemItem: .add, target: self, action: #selector(addNewWord))

print("languages array is: \(languages)")

clear.backgroundColor = .init(white: 0.95, alpha: 1.0)

clear.layer.cornerRadius = 5

clear.layer.borderWidth = 3

clear.layer.borderColor = UIColor.clear.cgColor

reset.backgroundColor = .init(white: 0.95, alpha: 1.0)

reset.layer.cornerRadius = 5

reset.layer.borderWidth = 3

reset.layer.borderColor = UIColor.clear.cgColor

sort.backgroundColor = .init(white: 0.95, alpha: 1.0)

sort.layer.cornerRadius = 5

sort.layer.borderWidth = 3

sort.layer.borderColor = UIColor.clear.cgColor


languagePicker.backgroundColor = .init(white: 0.95, alpha: 1.0)

languagePicker.layer.cornerRadius = 5

languagePicker.layer.borderWidth = 3

languagePicker.layer.borderColor = UIColor.clear.cgColor


sortEnableDisable()

clearEnableDisable()

resetEnableDisable()

}


func languageChosen(_ chosenLanguage: String) {

navigationItem.title = "\(chosenLanguage.capitalized) Words"

loadInitialValues()

tableView.reloadData()

}


func loadLanguages() {

if let defaults = UserDefaults(suiteName: "group.co.uk.tirnaelectronics.hyperpolyglot.todayview") {

if var savedLanguages = defaults.object(forKey: "savedLanguages") as? [String] {

print("savedLanguages in loadLanguages in WordsViewController are: \(savedLanguages)")

languages.removeAll()

languages = savedLanguages

savedLanguages.removeAll()

print("savedLanguages in loadLanguages in WordsViewController after removeAll: \(savedLanguages)")

print("languages in loadLanguages in WordsViewController are: \(languages)")

}

}

}


func chosenLanguageLoad() {

if let defaults = UserDefaults(suiteName: "group.co.uk.tirnaelectronics.hyperpolyglot.todayview") {

if let loadChosenLanguage = defaults.object(forKey: "languageChosen") as? String {

chosenLanguage = loadChosenLanguage

print("Chosen language in chosenLanguageLoad in WordsViewController is: \(chosenLanguage)")

}

}

}


@objc func loadInitialValues() {

words.removeAll()

if let defaults = UserDefaults(suiteName: "group.co.uk.tirnaelectronics.hyperpolyglot.todayview") {

print("words in loadInitialValues in WordsViewController after clear all: \(words)")

print("chosenLanguage in loadInitialValues in WordsViewController is: \(chosenLanguage)")

if var savedWords = defaults.object(forKey: "words") as? [String] {

print("savedWords in loadInitialValues in WordsViewController are: \(savedWords)")

words = savedWords

savedWords.removeAll()

print("savedWords in loadInitialValues in WordsViewController after clear all: \(savedWords)")

} else {

print("calling saveInitialWordValues()")

saveInitialWordValues()

}

tableViewWords.removeAll()

print("chosenLanguage in loadInitialValues in WordsViewController is: \(chosenLanguage)")

for word in words {

let split = word.components(separatedBy: "::")

if split[7] == chosenLanguage {

tableViewWords.append(word)

}

}

print("tableViewWords in loadInitialValues in WordsViewController are: \(tableViewWords)")

}

}


func saveInitialWordValues() {

if let defaults = UserDefaults(suiteName: "group.co.uk.tirnaelectronics.hyperpolyglot.todayview") {

words.removeAll()

words.append("Bear::Baissespekulant::0::0::0::0::0::german")

words.append("Camel::Kamel::0::0::0::0::0::german")

words.append("Cow::Rind::0::0::0::0::0::german")

words.append("Fox::Fuchs::0::0::0::0::0::german")

words.append("Goat::Geiß::0::0::0::0::0::german")

words.append("Monkey::Affe::0::0::0::0::0::german")

words.append("Pig::Schwein::0::0::0::0::0::german")

words.append("Rabbit::Karnickel::0::0::0::0::0::german")

words.append("Sheep::Schaf::0::0::0::0::0::german")

words.append("Bear::L'ours::0::0::0::0::0::french")

words.append("Camel::Le chameau::0::0::0::0::0::french")

words.append("Cow::La vache::0::0::0::0::0::french")

words.append("Fox::Le renard::0::0::0::0::0::french")

words.append("Goat::La chèvre::0::0::0::0::0::french")

words.append("Monkey::Le singe::0::0::0::0::0::french")

words.append("Pig::Le cochon::0::0::0::0::0::french")

words.append("Rabbit::Le lapin::0::0::0::0::0::french")

words.append("Sheep::Le mouton::0::0::0::0::0::french")

print("words in saveInitialWordValues in LanguagesViewController are: \(words)")

print("At end of saveInitialWordValues")

defaults.set(words, forKey: "words")

}

}


override func viewWillAppear(_ animated: Bool) {

super.viewWillAppear(animated)

loadLanguages()

print("languages in viewWillAppear in WordsViewController are: \(languages)")

chosenLanguageLoad()

navigationItem.title = "\(chosenLanguage.capitalized) Words"

loadInitialValues()

print("loadInitialValues in viewWillAppear in WordsViewController are: \(tableViewWords)")

clearEnableDisable()

resetEnableDisable()

sortEnableDisable()

tableView.reloadData()

}


func numberOfSections(in tableView: UITableView) -> Int {

return 1

}


func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {

print("number of tableViewWords in tableView(numberOfRowsInSection) are: \(tableViewWords.count)")

return tableViewWords.count

}


func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

//print("In cellForRowAt function")

let cell = tableView.dequeueReusableCell(withIdentifier: "Word", for: indexPath)

let tableViewWord = tableViewWords[indexPath.row]

if tableViewWord != "::" {

let split = tableViewWord.components(separatedBy: "::")

print(split[0])

cell.textLabel?.text = split[0]

cell.detailTextLabel?.text = ""

//print(cell)

}

return cell

}

}


The pop over controller class.



import UIKit


protocol LanguagesPopOverDelegate: class {

func languageChosen(_ chosenLanguage: String)

}


class LanguagesPopOverController: UIViewController, UIPickerViewDelegate, UIPickerViewDataSource {


@IBOutlet weak var picker: UIPickerView!

@IBOutlet weak var done: UIButton!

@IBOutlet weak var cancel: UIButton!

weak var delegate: LanguagesPopOverDelegate?

var languages = [String]()

var chosenLanguage = String()


override func viewDidLoad() {

super.viewDidLoad()


// Do any additional setup after loading the view.

loadLanguages()


view.frame.size.height = 324


picker.delegate = self

picker.dataSource = self

picker.reloadAllComponents()


done.backgroundColor = .init(white: 0.95, alpha: 1.0)

done.layer.cornerRadius = 5

done.layer.borderWidth = 3

done.layer.borderColor = UIColor.clear.cgColor

cancel.backgroundColor = .init(white: 0.95, alpha: 1.0)

cancel.layer.cornerRadius = 5

cancel.layer.borderWidth = 3

cancel.layer.borderColor = UIColor.clear.cgColor

}


// Number of columns of data

func numberOfComponents(in picker: UIPickerView) -> Int {

return 1

}


// The number of rows of data

func pickerView(_ picker: UIPickerView, numberOfRowsInComponent component: Int) -> Int {

print("Number of languages are: \(languages.count)")

return languages.count

}


// The data to return for the row and component (column) that's being passed in

func pickerView(_ picker: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {

return languages[row].capitalized

}


// Capture the picker view selection

func pickerView(_ picker: UIPickerView, didSelectRow row: Int, inComponent component: Int) {

// This method is triggered whenever the user makes a change to the picker selection.

// The parameter named row and component represents what was selected.

chosenLanguage = languages[row]

print("chosenLanguage in pickerView in LanguagePickerViewController is: \(chosenLanguage)")

}


func chooseALanguage() {

delegate?.languageChosen(chosenLanguage)

}


@IBAction func done(_ sender: Any) {

chosenLanguageSave()

let languagesPopOverVC = LanguagesPopOverController()

let wordsVC = WordsViewController()

languagesPopOverVC.delegate = wordsVC

languagesPopOverVC.chooseALanguage()

//wordsVC.chosenLanguage = self.chosenLanguage

//let languagesVC = LanguagesViewController()

//languagesVC.chosenLanguage = self.chosenLanguage

//let homeworkVC = HomeworkViewController()

//homeworkVC.chosenLanguage = self.chosenLanguage

//let testVC = TestViewController()

//testVC.chosenLanguage = self.chosenLanguage

dismiss(animated: true, completion: nil)

}


@IBAction func cancel(_ sender: Any) {

dismiss(animated: true, completion: nil)

}


func chosenLanguageSave() {

if let defaults = UserDefaults(suiteName: "group.co.uk.tirnaelectronics.hyperpolyglot.todayview") {

defaults.set(chosenLanguage, forKey: "languageChosen")

print("chosenLanguage in chosenLanguageSave in LanguagesPopOverController is: \(chosenLanguage)")

}

}


func loadLanguages() {

if let defaults = UserDefaults(suiteName: "group.co.uk.tirnaelectronics.hyperpolyglot.todayview") {

if var savedLanguages = defaults.object(forKey: "savedLanguages") as? [String] {

print("savedLanguages in loadLanguages in LanguagesPopOverController are: \(savedLanguages)")

languages.removeAll()

languages = savedLanguages

savedLanguages.removeAll()

print("savedLanguages in loadLanguages in LanguagesPopOverController after removeAll: \(savedLanguages)")

print("languages in loadLanguages in LanguagesPopOverController are: \(languages)")

}

}

}

}

Replies

It is a bit hard to follow track of code logic.


So, first question.

In LanguagesPopOverController you declare a var chosenLanguage (1)

You also declare a var chosenLanguage in WordsViewController (2)


I do not see how you expect to transfer var chosenLanguage (1) to WordsViewController


Second question, unless I missed something:

why do you define a new class LanguagesPopOverController

and not create the picker and the done button directly in WordsViewController

you could just hide them when they are not needed.

Could you elaborate on what you mean about creating the picker and done button directly in WordsViewController? My impression is that you're saying to avoid using a pop over controller, and show/hide the picker and done button when needed in WordsViewController. I choose a pop over controller as placing the picker view in words controller would interfere with the words table view and 4 buttons I have arranged horizontally just above the top of the tabe view in the words controller.

Please try to clarify viewcontroller-transition hierarchy of your app. You are just saying using segue but not showing from which VC nor to VC.


Anyway, your `done(_:)` of `LanguagesPopOverController` would never work as you expect.

You are creating two new view controllers and doing something on them, which has no effect on the actual view controllers in your app.


If you are using segue, you need to access `sourceViewController` and `destinationViewController`, do not instantiate viewcontrollers.