使用从popover pickerview中选择的字符串数组自动刷新tableview
Posted
技术标签:
【中文标题】使用从popover pickerview中选择的字符串数组自动刷新tableview【英文标题】:Automatically refreshing tableview with string array chosen from popover pickerview 【发布时间】:2019-07-28 22:11:27 【问题描述】:当用户点击一个按钮时,我试图让一个 tableview 更新其行,该按钮会在弹出控制器中显示可用语言的选择器查看器,然后更改语言。
我试图从弹出控制器的完成按钮方法中重新加载表格视图。我还尝试从 tableview 的类的 viewDidAppear() 和 viewWillAppear() 方法重新加载 tableview。以上都没有达到预期的效果。
import UIKit
class LanguagesPopOverController: UIViewController, UIPickerViewDelegate, UIPickerViewDataSource
//@IBOutlet var tableView: UITableView!
@IBOutlet weak var picker: UIPickerView!
@IBOutlet weak var done: UIButton!
@IBOutlet weak var cancel: UIButton!
var languages = [String]()
var chosenLanguage = String()
override func viewDidLoad()
super.viewDidLoad()
// Do any additional setup after loading the view.
loadLanguages()
//tableView.allowsMultipleSelection = false
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)")
@IBAction func done(_ sender: Any)
chosenLanguageSave()
let wordsVC = WordsViewController()
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)")
WordsViewController:
import UIKit
class WordsViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, UITabBarControllerDelegate, UIPopoverPresentationControllerDelegate
@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 chosenLanguageWords = [String]()
var chosenWords = [String]()
var useHomework: Bool!
var languages = [String]()
var language = String()
var chosenLanguage = String()
var textField: UITextField?
let wordString = "Words"
override func viewDidLoad()
super.viewDidLoad()
loadLanguages()
chosenLanguageLoad()
loadInitialValues()
print("chosenLanguage in viewDidLoad in WordsViewController is: \(chosenLanguage)")
//loadInitialValues()
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
reset.isEnabled = true
sort.backgroundColor = .init(white: 0.95, alpha: 1.0)
sort.layer.cornerRadius = 5
sort.layer.borderWidth = 3
sort.layer.borderColor = UIColor.clear.cgColor
// Need to write in a check to see if words array is alphabetically ordered
disableSort()
//homeworkOrChosen.titleLabel?.text = "Chosen"
@IBAction func languagePicker(_ sender: UIButton)
//let chooseLanguageContent = self.storyboard?.instantiateViewController(withIdentifier: "LanguagePickerPopOver")
//let chooseLanguageNav = UINavigationController(rootViewController: chooseLanguageContent!)
//chooseLanguageContent?.modalPresentationStyle = UIModalPresentationStyle.popover
//let languagePicker = chooseLanguageNav.popoverPresentationController
//chooseLanguageContent?.preferredContentSize = CGSize(width: 100,height: 100)
//languagePicker?.delegate = self
//languagePicker?.sourceView = self.view
//languagePicker?.sourceRect = CGRect(x: 100,y: 100,width: 300,height: 300)
//self.present(chooseLanguageNav, animated: true, completion: nil)
//let LPView = LanguagesPopOverController()
//LPView.languages = self.languages
//print("languages passed to LanguagePickerViewController are: \(LPView.languages)")
//present(chooseLanguageContent!, animated: true, completion: nil)
override func shouldPerformSegue(withIdentifier EditWords: String, sender: Any?) -> Bool
return true
override func prepare(for segue: UIStoryboardSegue, sender: Any?)
if let testVC = segue.destination as? TestViewController
testVC.useHomework = self.useHomework
@IBAction func clear(_ sender: UIButton)
// create an alert to get user to confirm intentions
let ac = UIAlertController(title: "Clear Words", message: "Are you sure you want to delete words?", preferredStyle: .alert)
// add user actions, "OK" to confirm, and "Cancel" to abort
ac.addAction(UIAlertAction(title: "Current Language", style: .default, handler: clearWords))
ac.addAction(UIAlertAction(title: "All Languages", style: .default, handler: clearAllWords))
ac.addAction(UIAlertAction(title: "Cancel", style: .cancel))
// present the alert controller to the user
present(ac, animated: true)
func clearWords(action: UIAlertAction!)
words.removeAll()
print("words in clearWords after removeAll in WordsViewController are: \(words)")
chosenLanguageWords.removeAll()
print("chosenLanguageWords in clearAll after removeAll in WordsViewController are: \(chosenLanguageWords)")
saveWords()
tableView.reloadData()
disableSort()
func clearAllWords(action: UIAlertAction!)
clearWordsAllLanguages()
disableSort()
func clearWordsAllLanguages()
if let defaults = UserDefaults(suiteName: "group.co.uk.tirnaelectronics.hyperpolyglot.todayview")
defaults.removeObject(forKey: "words")
words.removeAll()
print("words in clearWords after removeAll in WordsViewController are: \(words)")
chosenLanguageWords.removeAll()
print("chosenLanguageWords in clearAll after removeAll in WordsViewController are: \(chosenLanguageWords)")
saveWords()
disableSort()
tableView.reloadData()
@IBAction func reset(_ sender: UIButton)
// create an alert to get user to confirm intentions
let ac = UIAlertController(title: "Reset Words", message: "Are you sure you want to delete all your created words, including homework, and use starter words?", preferredStyle: .alert)
// add user actions, "OK" to confirm, and "Cancel" to abort
ac.addAction(UIAlertAction(title: "OK", style: .default, handler: resetWords))
ac.addAction(UIAlertAction(title: "Cancel", style: .cancel))
// present the alert controller to the user
present(ac, animated: true)
func resetWords(action: UIAlertAction!)
if let defaults = UserDefaults(suiteName: "group.co.uk.tirnaelectronics.hyperpolyglot.todayview")
defaults.removeObject(forKey: "words")
loadInitialValues()
tableView.reloadData()
@IBAction func sort(_ sender: UIButton)
words.sort()
tableView.reloadData()
disableSort()
func enableSort()
sort.isEnabled = true
sort.alpha = 1
func disableSort()
sort.isEnabled = false
sort.alpha = 0.25
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)")
@objc func test()
if chosenLanguageWords.isEmpty
let ac = UIAlertController(title: "Add Some Words!", message: nil, preferredStyle: .alert)
let okAction = UIAlertAction(title: "OK", style: .default)
ac.addAction(okAction)
present(ac, animated: true)
else
useHomework = false
self.performSegue(withIdentifier: "Test", sender: self)
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
saveInitialWordValues(to: defaults)
chosenLanguageWords.removeAll()
for word in words
let split = word.components(separatedBy: "::")
if split[7] == chosenLanguage
chosenLanguageWords.append(word)
func saveInitialWordValues(to defaults: UserDefaults)
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)
chosenLanguageLoad()
navigationItem.title = "\(chosenLanguage.capitalized) Words"
loadInitialValues()
tableView.reloadData()
override func viewDidAppear(_ animated: Bool)
navigationController?.setToolbarHidden(true, animated: false)
super.viewDidAppear(animated)
chosenLanguageLoad()
navigationItem.title = "\(chosenLanguage.capitalized) Words"
loadInitialValues()
tableView.reloadData()
override func viewWillDisappear(_ animated: Bool)
super.viewWillDisappear(animated)
@objc func addNewWord()
// create our alert controller
let ac = UIAlertController(title: "Add new word", message: nil, preferredStyle: .alert)
// add two text fields, one for English and one for foreign word
ac.addTextField textField in
textField.placeholder = "English"
ac.addTextField (textField) in
textField.placeholder = "\(self.chosenLanguage.capitalized)"
// create an "Add Word" button that submits the user's input
let submitAction = UIAlertAction(title: "Add Word", style: .default) [unowned self, ac] (action: UIAlertAction!) in
// pull out the English and foreign words, or an empty string if there was a problem
let firstWord = ac.textFields?[0].text?.capitalized ?? ""
let secondWord = ac.textFields?[1].text?.capitalized ?? ""
let zeroTimesWrong = "0"
let homeworkZeroTimesWrong = "0"
let attemptCount = "0"
let homeworkAttemptCount = "0"
let homeworkSet = "0"
let languageAdded = self.chosenLanguage
if self.chosenLanguageWords.contains("\(firstWord)") || self.chosenLanguageWords.contains("\(secondWord)")
self.wordsExistAlert()
else
// submit the English and foreign word to the insertFlashcard() method
self.insertFlashcard(first: firstWord, second: secondWord, third: zeroTimesWrong, fourth: homeworkZeroTimesWrong, fifth: attemptCount, sixth: homeworkAttemptCount, seventh: homeworkSet, eigth: languageAdded)
self.enableSort()
// add the submit action, plus a cancel button
ac.addAction(submitAction)
ac.addAction(UIAlertAction(title: "Cancel", style: .cancel))
// present the alert controller to the user
present(ac, animated: true)
func wordsExistAlert()
let ac = UIAlertController(title: "Already exists!", message: "Word(s) previously entered!", preferredStyle: .alert)
let okAction = UIAlertAction(title: "OK", style: .default)
ac.addAction(okAction)
self.present(ac, animated: true)
func insertFlashcard(first: String, second: String, third: String, fourth: String, fifth: String, sixth: String, seventh: String, eigth: String)
guard first.count > 0 && second.count > 0 else return
chosenLanguageWords.append("\(first)::\(second)::\(third)::\(fourth)::\(fifth)::\(sixth)::\(seventh)::\(eigth)")
saveWords()
let newIndexPath = IndexPath(row: chosenLanguageWords.count - 1, section: 0)
tableView.insertRows(at: [newIndexPath], with: .automatic)
func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration?
let delete = UIContextualAction(style: .destructive, title: "Delete")
(action, sourceView, completionHandler) in
self.chosenLanguageWords.remove(at: indexPath.row)
self.saveWords()
tableView.beginUpdates()
tableView.deleteRows(at: [indexPath], with: .left)
tableView.endUpdates()
// delete item at indexPath
self.enableSort()
completionHandler(true)
let edit = UIContextualAction(style: .normal, title: "Edit")
(action, sourceView, completionHandler) in
let ac = UIAlertController(title: "Edit word", message: nil, preferredStyle: .alert)
// add two text fields, one for English and one for foreign word
ac.addTextField textField in
let chosenLanguageWord = self.chosenLanguageWords[indexPath.row]
let split = chosenLanguageWord.components(separatedBy: "::")
let englishWord = split[0]
textField.placeholder = "\(englishWord)"
ac.addTextField (textField) in
let chosenLanguageWord = self.chosenLanguageWords[indexPath.row]
let split = chosenLanguageWord.components(separatedBy: "::")
let foreignWord = split[1]
textField.placeholder = "\(foreignWord)"
// create an "Edit Word" button that submits the user's input
let submitAction = UIAlertAction(title: "Edit Word", style: .default) [unowned self, ac] (action: UIAlertAction!) in
// pull out the English and foreign words, or an empty string if there was a problem
let firstWord = ac.textFields?[0].text ?? ""
let secondWord = ac.textFields?[1].text ?? ""
guard firstWord.count > 0 && secondWord.count > 0 else return
// edit item at indexPath
let split = self.chosenLanguageWords[indexPath.row].components(separatedBy: "::")
let wrongCount = split[2]
let homeworkWrongCount = split[3]
let attemptCount = split[4]
let homeworkAttemptCount = split[5]
let homeworkSet = split[6]
let languageEdited = split[7]
self.chosenLanguageWords.remove(at: indexPath.row)
self.chosenLanguageWords.insert("\(firstWord)::\(secondWord)::\(wrongCount)::\(homeworkWrongCount)::\(attemptCount)::\(homeworkAttemptCount)\(homeworkSet)::\(languageEdited)", at: indexPath.row)
self.saveWords()
tableView.beginUpdates()
tableView.deleteRows(at: [indexPath], with: .automatic)
tableView.insertRows(at: [indexPath], with: .automatic)
tableView.endUpdates()
/*self.resetEnableDisable()
self.chosenLanguageLoad()
self.clearAllEnableDisable()
self.chosenLanguageLoad()*/
self.enableSort()
// add the submit action, plus a cancel button
ac.addAction(submitAction)
ac.addAction(UIAlertAction(title: "Cancel", style: .cancel))
// present the alert controller to the user
self.present(ac, animated: true)
completionHandler(true)
let homework = UIContextualAction(style: .normal, title: "Homework")
(action, sourceView, completionHandler) in
let chosenLanguageWord = self.chosenLanguageWords[indexPath.row]
print("words in tableView editActionsForRowAt in WordsViewController are: \(self.words)")
let split = chosenLanguageWord.components(separatedBy: "::")
if split[4] == "0"
let firstWord = split[0]
let secondWord = split[1]
let zeroTimesWrong = split[2]
let homeworkZeroTimesWrong = split[3]
let attemptCount = split[4]
let homeworkAttemptCount = split[5]
let homeworkSet = "1"
let language = split[7]
self.chosenLanguageWords.remove(at: indexPath.row)
self.chosenLanguageWords.insert("\(firstWord)"+"::"+"\(secondWord)"+"::"+"\(zeroTimesWrong)"+"::"+"\(homeworkZeroTimesWrong)"+"::"+"\(attemptCount)"+"::"+"\(homeworkAttemptCount)"+"::"+"\(homeworkSet)"+"::"+"\(language)", at: indexPath.row)
else
let firstWord = split[0]
let secondWord = split[1]
let zeroTimesWrong = split[2]
let homeworkZeroTimesWrong = split[3]
let attemptCount = split[4]
let homeworkAttemptCount = split[5]
let homeworkSet = "0"
let language = split[7]
self.chosenLanguageWords.remove(at: indexPath.row)
self.chosenLanguageWords.insert("\(firstWord)"+"::"+"\(secondWord)"+"::"+"\(zeroTimesWrong)"+"::"+"\(homeworkZeroTimesWrong)"+"::"+"\(attemptCount)"+"::"+"\(homeworkAttemptCount)"+"::"+"\(homeworkSet)"+"::"+"\(language)", at: indexPath.row)
self.saveWords()
completionHandler(true)
delete.backgroundColor = UIColor.systemRed
edit.backgroundColor = UIColor.systemBlue
homework.backgroundColor = UIColor.systemGreen
let swipeConfiguration = UISwipeActionsConfiguration(actions: [delete, edit, homework])
return swipeConfiguration
func numberOfSections(in tableView: UITableView) -> Int
return 1
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
print("number of chosenLanguageWords in tableView(numberOfRowsInSection) are: \(chosenLanguageWords.count)")
return chosenLanguageWords.count
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
//print("In cellForRowAt function")
let cell = tableView.dequeueReusableCell(withIdentifier: "Word", for: indexPath)
let chosenLanguageWord = chosenLanguageWords[indexPath.row]
if chosenLanguageWord != "::"
let split = chosenLanguageWord.components(separatedBy: "::")
print(split[0])
cell.textLabel?.text = split[0]
cell.detailTextLabel?.text = ""
//print(cell)
return cell
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)
tableView.deselectRow(at: indexPath, animated: true)
if let cell = tableView.cellForRow(at: indexPath)
if cell.detailTextLabel?.text == ""
let chosenLanguageWord = chosenLanguageWords[indexPath.row]
let split = chosenLanguageWord.components(separatedBy: "::")
cell.detailTextLabel?.text = split[1]
else
cell.detailTextLabel?.text = ""
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath)
chosenLanguageWords.remove(at: indexPath.row)
saveWords()
tableView.deleteRows(at: [indexPath], with: .automatic)
func saveWords()
if let defaults = UserDefaults(suiteName: "group.co.uk.tirnaelectronics.hyperpolyglot.todayview")
var i = 0
for word in words
print("i in saveWords in WordsViewController is: \(i)")
let split = word.components(separatedBy: "::")
if split[7] == chosenLanguage
words.remove(at: i)
print("words after remove at index in saveWords in WordsViewController are: \(words)")
if i > 0
i -= 0
else
i += 1
print("words before append in saveWords in WordsViewController are: \(words)")
words.append(contentsOf: chosenLanguageWords)
defaults.set(words, forKey: "words")
print("words in saveWords after defaults.set in WordsViewController are: \(words)")
tableview 应该加载与当前选择的语言相关的单词。用户可以通过点击 WordsViewController 中的语言按钮并从弹出窗口的选择器视图轮中选择一种语言来更改当前语言。
当在弹出框控制器中点击完成按钮时,弹出框消失,并且应显示新选择的语言的单词表视图。一旦弹出窗口消失,我不知道如何自动刷新表格视图行。当用户在标签栏控制器中点击不同的视图控制器时,表格视图会重新加载,然后再点击 WordsViewController。期望用户必须这样做是不可取的,因为表格视图应该在用户确认更改语言后更新。
【问题讨论】:
【参考方案1】:我建议你创建一个委托来处理语言更改的回调,就像
protocol LanguagesPopOverDelegate
func choseLanguage(_ language: String)
【讨论】:
我尝试理解本教程:medium.com/@jamesrochabrun/… 但我无法成功实施您的建议。以上是关于使用从popover pickerview中选择的字符串数组自动刷新tableview的主要内容,如果未能解决你的问题,请参考以下文章