I have a TableView with custom cells that have a TextField inside, unfortunately I get a Thread 1: Fatal error: Unexpectedly found nil while unwrapping an Optional value when I use them (press return or touch the screen outside the textField to get out of the placeholder).
Here is my code :
class WalletTableViewController: UIViewController, UITextFieldDelegate { var cryptosArray: [Cryptos] = [] override func viewDidLoad() { super.viewDidLoad() tableView.delegate = self loadCryptoArray() } func loadCryptoArray() { if UserDefaults.standard.object(forKey: "cryptosArray") != nil { if let decoded = UserDefaults.standard.object(forKey: "cryptosArray") as? Data? { let decodedCryptoArray = NSKeyedUnarchiver.unarchiveObject(with: decoded!) as! [Cryptos] cryptosArray = decodedCryptoArray } } } } The TableView extension :
extension WalletTableViewController: UITableViewDelegate, UITableViewDataSource { func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return cryptosArray.count } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let crypto = cryptosArray[indexPath.row] let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! WalletTableViewCell cell.setCrypto(crypto: crypto) cell.delegate = self cell.amountTextField.delegate = self return cell } func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { return 85 } func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) { if editingStyle == .delete { cryptosArray.remove(at: indexPath.row) tableView.deleteRows(at: [indexPath], with: .fade) let userDefaults = UserDefaults.standard let encodedData : Data = NSKeyedArchiver.archivedData(withRootObject: cryptosArray) userDefaults.set(encodedData, forKey: "cryptosArray") userDefaults.synchronize() } } } This is the delegate function for the TextField:
extension WalletTableViewController: CryptoCellDelegate { func cellAmountEntered(_ sender: Any) { if WalletTableViewCell().amountTextField.text == "" { return } let str = WalletTableViewCell().amountTextField.text let formatter = NumberFormatter() formatter.locale = Locale(identifier: "en_US") let dNumber = formatter.number(from: str!) let nDouble = dNumber! let eNumber = Double(truncating: nDouble) WalletTableViewCell().amountLabel.text = String(format:"%.8f", eNumber) UserDefaults.standard.set(WalletTableViewCell().amountLabel.text, forKey: "bitcoinAmount") WalletTableViewCell().amountTextField.text = "" } } The custom cell file :
protocol CryptoCellDelegate { func cellAmountEntered(_ sender: Any) } class WalletTableViewCell: UITableViewCell { @IBOutlet weak var cryptoNameLabel: UILabel! @IBOutlet weak var amountLabel: UILabel! @IBOutlet weak var amountTextField: UITextField! var cryptoItem: Crypto! var delegate: CryptoCellDelegate? func setCrypto(crypto: Cryptos) { cryptoNameLabel.text = crypto.name } @IBAction func amountTextFieldEntered(_ sender: Any) { delegate?.cellAmountEntered((Any).self) } } The TableView has as many cells as the user wants, so this is depending on the array of objects that create the cells.
I guess I have a delegate problem somewhere? I am quite new to UITableView so this has been quite a challenge, forgive any stupid blunder :)
PS: I've tried to keep the code short by removing keyboard functions and unrelated stuff, please tell me if you need something else.