自定义 UITableViewCell 中的 UITextField 意外发现 nil
Posted
技术标签:
【中文标题】自定义 UITableViewCell 中的 UITextField 意外发现 nil【英文标题】:UITextField in custom UITableViewCell unexpectedly found nil 【发布时间】:2018-03-01 10:04:52 【问题描述】:我有一个 TableView
带有自定义单元格,里面有一个 TextField
,不幸的是我得到一个 Thread 1: Fatal error: Unexpectedly found nil while unwrapping an Optional value 当我使用它们时(按回车键或触摸文本字段外的屏幕以退出占位符)。
这是我的代码:
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
TableView
扩展:
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()
这是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 = ""
自定义单元格文件:
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)
TableView
拥有用户想要的尽可能多的单元格,因此这取决于创建单元格的对象的 array
。
我想我在某个地方遇到了delegate
问题?我对UITableView
很陌生,所以这是一个相当大的挑战,请原谅任何愚蠢的错误:)
PS:我试图通过删除 keyboard
函数和不相关的东西来保持代码简短,如果您需要其他内容,请告诉我。
【问题讨论】:
更新extension WalletTableViewController: CryptoCellDelegate
中的代码,因为它现在显然无法编译
粘贴技巧不好,抱歉
检查更新的答案
也许你的文本字段的文本不是整数值测试这个let dNumber = Int(str) ? Int(str) : 0
而不是这个let dNumber = formatter.number(from: str!)
【参考方案1】:
在您使用WalletTableViewCell()
的任何地方,您都在创建WalletTableViewCell
的新实例。发生崩溃是因为您以编程方式创建它,而 WalletTableViewCell
是使用情节提要设计的,并且由于您没有使用情节提要对其进行实例化,因此尚未设置 @IBOutlet
s,因此是 nil
。
更新
尝试使用它来修复它。将CryptoCellDelegate
更新为:
protocol CryptoCellDelegate
func cellAmountEntered(_ walletTableViewCell: WalletTableViewCell)
然后在WalletTableViewCell
更新amountTextFieldEntered
为:
@IBAction func amountTextFieldEntered(_ sender: Any)
delegate?.cellAmountEntered(self)
最后更新委托实现:
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 = ""
【讨论】:
Milan 你好 :) 我以为我引用了WalletTableViewCell
,我真的需要再研究一下。我还认为委派函数足以使用WalletTableViewCell
出口和操作,这是否意味着我必须在WalletTableViewController
中再次声明所有内容?
@Martin33000 很高兴为您提供帮助
作为建议@Martin33000,避免使用ClassName()
,而是使用ClassName.init()
。应该是一样的,然后教/提醒你,你每次都创建一个全新的对象,直到你吸收它。此外,由于该单元格与 XIB(或 Storyboard)链接,因此 IBOutlets 连接在那里,但没有该“UI 链接”就不会阻止您进行初始化。而且因为你做了init()
,它没有创建一个与XIB链接的对象,所以Outlets是nil。以上是关于自定义 UITableViewCell 中的 UITextField 意外发现 nil的主要内容,如果未能解决你的问题,请参考以下文章
在 Storyboard 中设计的自定义 UITableViewCell 中的自定义 UIView
ios开发UI篇—使用纯代码自定义UItableviewcell实现一个简单的微博界面布局
iOS开发UI篇—使用xib自定义UItableviewcell实现一个简单的团购应用界面布局
将自定义 UITableViewCell 从 nib 加载到 Swift 中的 UIViewController