UITextField in custom UITableViewCell unexpectedly found nil

匿名 (未验证) 提交于 2019-12-03 02:34:02

问题:

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.

回答1:

Everywhere where you use WalletTableViewCell() you are creating a new instance of the WalletTableViewCell. The crash happens because you are creating it programmatically, while WalletTableViewCell was designed using storyboards, and since you did not instantiated it using storyboards, @IBOutlets have not been set, therefore are nil.

Update

Try to fix it using this. Update CryptoCellDelegate to this:

protocol CryptoCellDelegate {     func cellAmountEntered(_ walletTableViewCell: WalletTableViewCell) } 

Then in WalletTableViewCell update amountTextFieldEntered to:

@IBAction func amountTextFieldEntered(_ sender: Any) {     delegate?.cellAmountEntered(self) } 

And finally update delegate implementation:

extension WalletTableViewController: CryptoCellDelegate {     func cellAmountEntered(_ walletTableViewCell: WalletTableViewCell) {         // now you can use walletTableViewCell to access the cell that called the delegate method         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 = ""      } } 


易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!