The cellForRowAt method in line 240 is to return cells in a UITableView with a word from an array. None of the method's print statements appear in the debug console, but all others do (contents of words array, and ones that state where in the program its currently executing. Originally I had one userDefaults dictionary and the cellForRowAt method worked. The addNewWord and startTest methods completely work, so the words array is being created from the userDefaults dictionary when there are 2 keys. I believe the problem to be with cellForRowAt, although that's the same code as when it worked with 1 userDictionay key. Ever since 2 userDictionary keys were used, this problem has happened.
//
// ViewController.swift
// Polyglot
//
// Created by Alan Dripps on 01/02/2019.
// Copyright © 2019 Alan Dripps. All rights reserved.
//
import UIKit
class ViewController: UITableViewController {
var words = [String]()
var choosenLanguage = String()
override func viewDidLoad() {
super.viewDidLoad()
let titleAttributes = [NSAttributedString.Key.font: UIFont(name: "AmericanTypewriter", size: 22)!]
navigationController?.navigationBar.titleTextAttributes = titleAttributes
title = "POLYGLOT"
let chooseLanguage = UIAlertController(title: "Vocabulary Tutor", message: "Choose a Language", preferredStyle: .actionSheet)
let germanButton = UIAlertAction(title: "German", style: .default, handler: { (action) -> Void in
self.choosenLanguage = "german"
print("Choosen language is: \(self.choosenLanguage)")
self.loadInitialValues()
})
let frenchButton = UIAlertAction(title: "French", style: .default, handler: { (action) -> Void in
self.choosenLanguage = "french"
print("Choosen language is: \(self.choosenLanguage)")
self.loadInitialValues()
})
chooseLanguage.addAction(germanButton)
chooseLanguage.addAction(frenchButton)
self.navigationController!.present(chooseLanguage, animated: true, completion: nil)
}
func loadInitialValues(){
if let defaults = UserDefaults(suiteName: "group.co.uk.tirnaelectronics.polyglot") {
if choosenLanguage == "german" {
print("In load initial values german choosen")
if let savedWords = defaults.object(forKey: "germanWords") as? [String] {
words = savedWords
} else {
saveInitialGermanValues(to: defaults)
}
} else if choosenLanguage == "french" {
print("In load initial values french choosen")
if let savedWords = defaults.object(forKey: "frenchWords") as? [String] {
words = savedWords
} else {
saveInitialFrenchValues(to: defaults)
}
}
print(words)
print("Number of words: \(words.count)")
}
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
navigationItem.leftBarButtonItem = UIBarButtonItem(barButtonSystemItem: .add, target: self, action: #selector(addNewWord))
navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: .play, target: self, action: #selector(startTest))
navigationItem.backBarButtonItem = UIBarButtonItem(title: "End Test", style: .plain, target: nil, action: nil)
}
@objc func startTest() {
guard let vc = storyboard?.instantiateViewController(withIdentifier: "Test") as? TestViewController else { return }
vc.words = words
navigationController?.pushViewController(vc, animated: true)
}
func saveInitialGermanValues(to defaults: UserDefaults) {
words.append("Bear::Baissespekulant")
words.append("Camel::Kamel")
words.append("Cow::Rind")
words.append("Fox::Fuchs")
words.append("Goat::Geiß")
words.append("Monkey::Affe")
words.append("Pig::Schwein")
words.append("Rabbit::Karnickel")
words.append("Sheep::Schaf")
print(words)
defaults.set(words, forKey: "germanWords")
print("At end of saveInitialGermanValues")
}
func saveInitialFrenchValues(to defaults: UserDefaults) {
words.append("Bear::l'ours")
words.append("Camel::le chameau")
words.append("Cow::la vache")
words.append("Fox::le renard")
words.append("Goat::la chèvre")
words.append("Monkey::le singe")
words.append("Pig::le cochon")
words.append("Rabbit::le lapin")
words.append("Sheep::le mouton")
print(words)
defaults.set(words, forKey: "frenchWords")
print("At end of saveInitialFrenchValues")
}
@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 French
ac.addTextField { textField in
textField.placeholder = "English"
}
ac.addTextField { (textField) in
switch self.choosenLanguage {
case "german":
textField.placeholder = "German"
case "french":
textField.placeholder = "French"
default:
print("Choose a language")
}
}
// 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 French words, or an empty string if there was a problem
let firstWord = ac.textFields?[0].text ?? ""
let secondWord = ac.textFields?[1].text ?? ""
// submit the English and French word to the insertFlashcard() method
self.insertFlashcard(first: firstWord, second: secondWord)
}
// 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 insertFlashcard(first: String, second: String) {
guard first.count > 0 && second.count > 0 else { return }
let newIndexPath = IndexPath(row: words.count, section: 0)
words.append("\(first)::\(second)")
tableView.insertRows(at: [newIndexPath], with: .automatic)
saveWords()
}
override func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]? {
let delete = UITableViewRowAction(style: .default, title: "Delete") { action, indexPath in
self.words.remove(at: indexPath.row)
tableView.beginUpdates()
tableView.deleteRows(at: [indexPath], with: .left)
tableView.endUpdates()
// delete item at indexPath
}
let edit = UITableViewRowAction(style: .normal, title: "Edit") { (action, indexPath) in
let ac = UIAlertController(title: "Edit word", message: nil, preferredStyle: .alert)
// add two text fields, one for English and one for French
ac.addTextField { textField in
let word = self.words[indexPath.row]
let split = word.components(separatedBy: "::")
let englishWord = split[0]
textField.placeholder = "\(englishWord)"
}
ac.addTextField { (textField) in
let word = self.words[indexPath.row]
let split = word.components(separatedBy: "::")
let foreignWord = split[1]
textField.placeholder = "\(foreignWord)"
}
// create an "Add 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 French 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
self.words.remove(at: indexPath.row)
self.words.insert("\(firstWord)::\(secondWord)", at: indexPath.row)
tableView.beginUpdates()
tableView.deleteRows(at: [indexPath], with: .automatic)
tableView.insertRows(at: [indexPath], with: .automatic)
tableView.endUpdates()
self.saveWords()
}
// 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)
}
edit.backgroundColor = UIColor.blue
return [delete, edit]
}
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return words.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
print("In cellForRowAt function")
let cell = tableView.dequeueReusableCell(withIdentifier: "Word", for: indexPath)
let word = words[indexPath.row]
let split = word.components(separatedBy: "::")
print(split[0])
cell.textLabel?.text = split[0]
cell.detailTextLabel?.text = ""
print(cell)
return cell
}
override 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 word = words[indexPath.row]
let split = word.components(separatedBy: "::")
cell.detailTextLabel?.text = split[1]
} else {
cell.detailTextLabel?.text = ""
}
}
}
override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
words.remove(at: indexPath.row)
tableView.deleteRows(at: [indexPath], with: .automatic)
saveWords()
}
func saveWords() {
if let defaults = UserDefaults(suiteName: "group.co.uk.tirnaelectronics.polyglot") {
if choosenLanguage == "german" {
defaults.set(words, forKey: "germanWords")
} else if choosenLanguage == "french" {
defaults.set(words, forKey: "frenchWords")
}
}
}
}