致命错误:在展开可选值时意外发现 nil - 当 UITextField 被点击时
Posted
技术标签:
【中文标题】致命错误:在展开可选值时意外发现 nil - 当 UITextField 被点击时【英文标题】:fatal error: unexpectedly found nil while unwrapping an Optional value - when UITextField is tapped 【发布时间】:2016-01-22 12:14:16 【问题描述】:我在其中一个 UITableViewCell 行中有一个 UITextField。当我选择该行时,将调用文本字段的委托方法。但是,当我直接点击 UITextField 时,应用程序崩溃并出现以下错误,
致命错误:在展开可选值时意外发现 nil
只有在点击 UITextField 时应用才会崩溃。使用给定数据正确加载了 tableView。
这是代码,
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
let cell = UITableViewCell(style: UITableViewCellStyle.Subtitle, reuseIdentifier: "Cell")
cell.detailTextLabel?.hidden = true
let txtFld = UITextField()
cell.contentView.addSubview(txtFld)
txtFld.tintColor = appGlobals.appThemeColor
txtFld.delegate = self
txtFld.textColor = appGlobals.appThemeColor
txtFld.returnKeyType = UIReturnKeyType.Done
txtFld.keyboardType = UIKeyboardType.EmailAddress
txtFld.autocorrectionType = UITextAutocorrectionType.No
txtFld.autocapitalizationType = UITextAutocapitalizationType.None
txtFld.translatesAutoresizingMaskIntoConstraints = false
txtFld.text = self.appGlobals.getSelectedContactEmail()
txtFld.tag = 99
cell.addConstraint(NSLayoutConstraint(item: txtFld, attribute: NSLayoutAttribute.Top, relatedBy: NSLayoutRelation.Equal, toItem: cell.textLabel, attribute: NSLayoutAttribute.Top, multiplier: 1, constant: 15))
cell.addConstraint(NSLayoutConstraint(item: txtFld, attribute: NSLayoutAttribute.Width, relatedBy: NSLayoutRelation.Equal, toItem: nil, attribute: NSLayoutAttribute.Width, multiplier: 1, constant: cell.frame.size.width - 30))
cell.addConstraint(NSLayoutConstraint(item: txtFld, attribute: NSLayoutAttribute.Height, relatedBy: NSLayoutRelation.Equal, toItem: nil, attribute: NSLayoutAttribute.Height, multiplier: 1, constant: 20))
cell.addConstraint(NSLayoutConstraint(item: txtFld, attribute: NSLayoutAttribute.Left, relatedBy: NSLayoutRelation.Equal, toItem: cell.textLabel, attribute: NSLayoutAttribute.Left, multiplier: 1, constant: 0))
cell.selectionStyle = UITableViewCellSelectionStyle.None
return cell
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath)
let txtField = cell.viewWithTag(99) as! UITextField
txtField.becomeFirstResponder()
还有 UITextField 委托方法,
func textFieldShouldBeginEditing(textField: UITextField) -> Bool
return true
func textFieldDidBeginEditing(textField: UITextField)
NSLog("text field became first responder")
更新1:
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
let cell = UITableViewCell(style: UITableViewCellStyle.Subtitle, reuseIdentifier: "Cell")
cell.detailTextLabel?.hidden = true
if(cell.contentView.viewWithTag(99) == nil)
let txtFld = UITextField()
cell.contentView.addSubview(txtFld)
txtFld.tintColor = appGlobals.appThemeColor
txtFld.delegate = self
txtFld.textColor = appGlobals.appThemeColor
txtFld.returnKeyType = UIReturnKeyType.Done
txtFld.keyboardType = UIKeyboardType.EmailAddress
txtFld.autocorrectionType = UITextAutocorrectionType.No
txtFld.autocapitalizationType = UITextAutocapitalizationType.None
txtFld.text = self.appGlobals.getSelectedContactEmail()
txtFld.tag = 99
cell.selectionStyle = UITableViewCellSelectionStyle.None
return cell
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath)
if let txtField = cell.contentView.viewWithTag(99) as? UITextField
txtField.becomeFirstResponder()
更新 2:
这是自定义表格视图单元格的代码,
import UIKit
class TxtFieldTableViewCell: UITableViewCell
let appGlobals = AppGlobals()
let txtFld = UITextField(frame: CGRectMake(15, 27, AppGlobals().getScreenWidth() - 30, 20))
override init(style: UITableViewCellStyle, reuseIdentifier: String?)
super.init(style: style, reuseIdentifier: reuseIdentifier)
txtFld.tintColor = appGlobals.appThemeColor
txtFld.textColor = appGlobals.appThemeColor
txtFld.returnKeyType = UIReturnKeyType.Done
txtFld.autocorrectionType = UITextAutocorrectionType.No
txtFld.autocapitalizationType = UITextAutocapitalizationType.None
self.addSubview(txtFld)
required init?(coder aDecoder: NSCoder)
fatalError("init(coder:) has not been implemented")
override func awakeFromNib()
super.awakeFromNib()
override func setSelected(selected: Bool, animated: Bool)
super.setSelected(selected, animated: animated)
我已经在我的代码中这样使用它,
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
var cell : TxtFieldTableViewCell? = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as? TxtFieldTableViewCell
if cell == nil
cell = TxtFieldTableViewCell(style: UITableViewCellStyle.Subtitle, reuseIdentifier: "Cell")
if(cell!.viewWithTag(99) == nil)
cell!.txtFld.delegate = self
cell!.txtFld.keyboardType = UIKeyboardType.EmailAddress
cell!.txtFld.text = self.appGlobals.getSelectedContactEmail()
cell!.txtFld.tag = 99
cell!.selectionStyle = UITableViewCellSelectionStyle.None
仍然遇到同样的错误。
【问题讨论】:
崩溃发生在哪一行? 我怀疑文本字段未正确启动 UITextField()。尝试用一些框架来初始化它,比如 UITextField(frame: someRect) 也可以试试 cell.contentView.viewWithTag(99)。请注意,txtField 是 contentView 的子视图,而不是单元格。 此代码不是最优的。每次调用cellForRowAtIndexPath
时,您都会创建一个新的文本字段并将其添加到表格视图单元格中......如果您正在滚动该表格视图,单元格会被重用,文本字段会一遍又一遍地添加到相同的(回收)细胞。您可能应该想出一种不同的方式来添加您的文本字段(例如子类 UITableViewCell?)。
没有特定的行发生崩溃。如果直接点击 UITextField,则应用程序崩溃。 @RamyKfoury
【参考方案1】:
你的代码中唯一可能发生错误的地方就是这个
let txtField = cell.viewWithTag(99) as! UITextField
txtField.becomeFirstResponder()
请改成以下,再试一次
if let txtField = cell.contentView.viewWithTag(99) as? UITextField
txtField.becomeFirstResponder()
如果这解决了问题,那么您的 TextField 没有很好地启动...尝试给它一个类似的框架
txtFld.frame = CGRectMake(0,0,40,40)
在将其添加为子视图之前
另外看看 Michael Dautermanns 的评论... TableViewCells 被重用了...所以你需要检查是否已经有标签为 99 的子视图,如果没有标签为 99 的子视图,则只添加一个新的子视图
【讨论】:
感谢您的回复。我已经尝试过你的建议。但是,我仍然遇到同样的错误。请检查我更新的帖子。 您没有设置文本字段的委托 我做到了。但是委托方法没有被调用@pbush25 我已经用 UITextField 委托方法更新了我的帖子。请检查它@pbush25 你的类没有声明自己符合 UITextViewDelegate【参考方案2】:我找到了我的应用程序崩溃的原因。我在 textFieldShouldBeginEditing 中使用了一个未初始化的变量。该变量是在 didSelectRowAtIndexPath 方法中初始化的。
我已经声明了一个这样的变量,
var selectedIndex: NSIndexPath!
我已经这样初始化了,
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath)
let cell = tableView.cellForRowAtIndexPath(indexPath)! as UITableViewCell
selectedIndex = indexPath
if let txtField = cell.viewWithTag(99) as? UITextField
txtField.becomeFirstResponder()
而变量是这样使用的,
func textFieldShouldBeginEditing(textField: UITextField) -> Bool
if(selectedIndex.section != 0)
//Some Operation
由于当我直接点击文本字段时selectedIndex
没有初始化,所以我的应用程序崩溃了。这就是问题所在。
感谢@Michael Dautermann 和@Neo 提出最佳解决方案。
【讨论】:
以上是关于致命错误:在展开可选值时意外发现 nil - 当 UITextField 被点击时的主要内容,如果未能解决你的问题,请参考以下文章
Alamofire,致命错误:在展开可选值时意外发现 nil