展开可选值 swift 时意外发现 nil
Unexpectedly found nil while unwrapping an Optional value swift
我从 Swift 收到一条错误消息 "Unexpectedly found nil
while unwrapping an Optional
",下面是 class。错误发生在行:
(cell.contentView.viewWithTag(1) as UILabel).text = object["firstName"] as? String
我有一个自定义单元格 class,带有 2 个标记为 1 和 2 的 UILabel,插座已设置
import UIKit
import Foundation
class dictionaryTableViewController: UIViewController, UITableViewDelegate, UITableViewDataSource{
var objects = NSMutableArray()
var dataArray = [["firstName":"Debasis","lastName":"Das","email":"debasis_das@knowstack.com"],["firstName":"John","lastName":"Doe","email":"jdoe@knowstack.com"],["firstName":"Jane","lastName":"Doe","email":"janedoe@knowstack.com"],["firstName":"Mary","lastName":"Jane","email":"mjane@knowstack.com"]]
@IBOutlet
var tableView: UITableView!
var items: [String] = ["We", "Heart", "Swift"]
override func viewDidLoad() {
super.viewDidLoad()
self.tableView.registerClass(UITableViewCell.self, forCellReuseIdentifier: "MyCell")
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return dataArray.count;//self.items.count;
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
//var cell:UITableViewCell = self.tableView.dequeueReusableCellWithIdentifier("cell") as UITableViewCell
//cell.textLabel?.text = self.items[indexPath.row]
//return cell
let cell = tableView.dequeueReusableCellWithIdentifier("MyCell", forIndexPath: indexPath) as UITableViewCell
let object = dataArray[indexPath.row] as NSDictionary
(cell.contentView.viewWithTag(1) as UILabel).text = object["firstName"] as? String
(cell.contentView.viewWithTag(2) as UILabel).text = object["lastName"] as? String
return cell
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
println("You selected cell #\(indexPath.row)!")
}
}
EDIT2:此解决方案可能更适合您的目的。有了这个,您可以为自己的 UITableViewCell 创建自己的 class 并将其与重用模式一起使用。评论在代码中:
class dictionaryTableViewController: UIViewController, UITableViewDelegate, UITableViewDataSource{
// The data
var dataArray = [["firstName":"Debasis","lastName":"Das","email":"debasis_das@knowstack.com"],["firstName":"John","lastName":"Doe","email":"jdoe@knowstack.com"],["firstName":"Jane","lastName":"Doe","email":"janedoe@knowstack.com"],["firstName":"Mary","lastName":"Jane","email":"mjane@knowstack.com"]]
// The outlet to your tableview in the ViewController in storyboard
@IBOutlet var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
// Create a nib for reusing
let nib = UINib(nibName: "MyCell", bundle: nil)
// Register the nib for reusing within the tableview with your reuseidentifier
tableView.registerNib(nib, forCellReuseIdentifier: "MyCell")
// Set delegate and datasource to self (you can do that in interface builder as well
tableView.delegate = self
tableView.dataSource = self
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return dataArray.count; // return the number of datasets
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
// create a reusable cell with the reuse identifier you registered in viewDidLoad and cast it to MyCell
let cell = tableView.dequeueReusableCellWithIdentifier("MyCell") as MyCell
let object = dataArray[indexPath.row] as NSDictionary
// set the strings matching your array
cell.label1.text = object["firstName"] as? String
cell.label2.text = object["lastName"] as? String
// return the cell
return cell
}
// some example for the delegate
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
println("You selected cell #\(indexPath.row)!")
}
}
// class for you own UITableViewCell
// has own xib file
class MyCell: UITableViewCell {
// two outlets representing two labels in the xib file
@IBOutlet private weak var label1: UILabel!
@IBOutlet private weak var label2: UILabel!
}
为此,您必须创建一个名称正确的 xib 文件(在本例中为 MyCell)。它应该与此类似:
设置自定义view和outlets的class很重要
------------------------------------ 其他解决方案 ------ ------------------------------
编辑:正如我所见,您没有初始化自己的 class ‘MyCell’,而是使用 reuseIdentifier ‘MyCell’ 初始化 Apple 的 class ‘UITableViewCell’。这就是使用 UITableViewCell 的解决方案:
行 (cell.contentView.viewWithTag(1) as UILabel)
不仅是对特定 class 的强制转换,它还展开了 Optional (UIView)。在其他情况下,您可以使用“!”来做到这一点。
所以问题是:您正在创建一个 UITableViewCell 的实例,一个 class Apple 创建的实例。您希望使用特定标签在该视图中获取子视图。你怎么知道苹果给了他们这些标签?您真正想要的是创建一个具有特殊样式的 UITableViewCell 实例,并像这样设置 textLabels 的值:
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
// Create an instance of UITableViewCell. Style is .Subtitle but could be others as well
var cell = tableView.dequeueReusableCellWithIdentifier("MyCell") as? UITableViewCell
let object = dataArray[indexPath.row] as NSDictionary
// set the strings matching your array
cell?.textLabel?.text = object["firstName"] as? String
cell?.detailTextLabel?.text = object["lastName"] as? String
// return the cell
return cell!
}
如果你想使用自定义单元格布局,我建议
子class UITableViewCell
:
// CustomTableViewCell.swift
import UIKit
class CustomTableViewCell: UITableViewCell {
@IBOutlet weak var firstNameLabel: UILabel!
@IBOutlet weak var lastNameLabel: UILabel!
}
在故事板中创建 table 视图。将单元格原型添加到情节提要中的 table 视图。设计该单元格原型(添加您想要的任何标签)。
将单元格原型的故事板标识符指定为您想要的任何内容(在您的示例中为MyCell
)。
指定单元格原型的基数 class,在此示例中,CustomTableViewCell
:
在您的单元格原型和您的 UITableViewCell
子class.
之间连接 IBOutlet
引用
注意 IBOutlet
参考左侧的实心项目符号。这表明插座已正确连接。
在您的数据源中实施 cellForRowAtIndexPath
,例如在 Swift 3:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "MyCell", for: indexPath) as! CustomTableViewCell
let person = dataArray[indexPath.row]
cell.firstNameLabel.text = person["firstName"]
cell.lastNameLabel.text = person["lastName"]
return cell
}
或在Swift 2:
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("MyCell", forIndexPath: indexPath) as! CustomTableViewCell
let person = dataArray[indexPath.row]
cell.firstNameLabel.text = person["firstName"]
cell.lastNameLabel.text = person["lastName"]
return cell
}
请注意,如果使用单元格原型,您不会想要在viewDidLoad
中调用registerClass
。 Storyboard 将自动为您使用重复使用的标识符注册您的自定义 class(因为您在步骤 3 和 4 中所做的)。
我所要做的就是:
cell.subviews[0].subviews[0].viewWithTag(//your tag//)
我从 Swift 收到一条错误消息 "Unexpectedly found nil
while unwrapping an Optional
",下面是 class。错误发生在行:
(cell.contentView.viewWithTag(1) as UILabel).text = object["firstName"] as? String
我有一个自定义单元格 class,带有 2 个标记为 1 和 2 的 UILabel,插座已设置
import UIKit
import Foundation
class dictionaryTableViewController: UIViewController, UITableViewDelegate, UITableViewDataSource{
var objects = NSMutableArray()
var dataArray = [["firstName":"Debasis","lastName":"Das","email":"debasis_das@knowstack.com"],["firstName":"John","lastName":"Doe","email":"jdoe@knowstack.com"],["firstName":"Jane","lastName":"Doe","email":"janedoe@knowstack.com"],["firstName":"Mary","lastName":"Jane","email":"mjane@knowstack.com"]]
@IBOutlet
var tableView: UITableView!
var items: [String] = ["We", "Heart", "Swift"]
override func viewDidLoad() {
super.viewDidLoad()
self.tableView.registerClass(UITableViewCell.self, forCellReuseIdentifier: "MyCell")
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return dataArray.count;//self.items.count;
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
//var cell:UITableViewCell = self.tableView.dequeueReusableCellWithIdentifier("cell") as UITableViewCell
//cell.textLabel?.text = self.items[indexPath.row]
//return cell
let cell = tableView.dequeueReusableCellWithIdentifier("MyCell", forIndexPath: indexPath) as UITableViewCell
let object = dataArray[indexPath.row] as NSDictionary
(cell.contentView.viewWithTag(1) as UILabel).text = object["firstName"] as? String
(cell.contentView.viewWithTag(2) as UILabel).text = object["lastName"] as? String
return cell
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
println("You selected cell #\(indexPath.row)!")
}
}
EDIT2:此解决方案可能更适合您的目的。有了这个,您可以为自己的 UITableViewCell 创建自己的 class 并将其与重用模式一起使用。评论在代码中:
class dictionaryTableViewController: UIViewController, UITableViewDelegate, UITableViewDataSource{
// The data
var dataArray = [["firstName":"Debasis","lastName":"Das","email":"debasis_das@knowstack.com"],["firstName":"John","lastName":"Doe","email":"jdoe@knowstack.com"],["firstName":"Jane","lastName":"Doe","email":"janedoe@knowstack.com"],["firstName":"Mary","lastName":"Jane","email":"mjane@knowstack.com"]]
// The outlet to your tableview in the ViewController in storyboard
@IBOutlet var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
// Create a nib for reusing
let nib = UINib(nibName: "MyCell", bundle: nil)
// Register the nib for reusing within the tableview with your reuseidentifier
tableView.registerNib(nib, forCellReuseIdentifier: "MyCell")
// Set delegate and datasource to self (you can do that in interface builder as well
tableView.delegate = self
tableView.dataSource = self
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return dataArray.count; // return the number of datasets
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
// create a reusable cell with the reuse identifier you registered in viewDidLoad and cast it to MyCell
let cell = tableView.dequeueReusableCellWithIdentifier("MyCell") as MyCell
let object = dataArray[indexPath.row] as NSDictionary
// set the strings matching your array
cell.label1.text = object["firstName"] as? String
cell.label2.text = object["lastName"] as? String
// return the cell
return cell
}
// some example for the delegate
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
println("You selected cell #\(indexPath.row)!")
}
}
// class for you own UITableViewCell
// has own xib file
class MyCell: UITableViewCell {
// two outlets representing two labels in the xib file
@IBOutlet private weak var label1: UILabel!
@IBOutlet private weak var label2: UILabel!
}
为此,您必须创建一个名称正确的 xib 文件(在本例中为 MyCell)。它应该与此类似:
设置自定义view和outlets的class很重要
------------------------------------ 其他解决方案 ------ ------------------------------
编辑:正如我所见,您没有初始化自己的 class ‘MyCell’,而是使用 reuseIdentifier ‘MyCell’ 初始化 Apple 的 class ‘UITableViewCell’。这就是使用 UITableViewCell 的解决方案:
行 (cell.contentView.viewWithTag(1) as UILabel)
不仅是对特定 class 的强制转换,它还展开了 Optional (UIView)。在其他情况下,您可以使用“!”来做到这一点。
所以问题是:您正在创建一个 UITableViewCell 的实例,一个 class Apple 创建的实例。您希望使用特定标签在该视图中获取子视图。你怎么知道苹果给了他们这些标签?您真正想要的是创建一个具有特殊样式的 UITableViewCell 实例,并像这样设置 textLabels 的值:
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
// Create an instance of UITableViewCell. Style is .Subtitle but could be others as well
var cell = tableView.dequeueReusableCellWithIdentifier("MyCell") as? UITableViewCell
let object = dataArray[indexPath.row] as NSDictionary
// set the strings matching your array
cell?.textLabel?.text = object["firstName"] as? String
cell?.detailTextLabel?.text = object["lastName"] as? String
// return the cell
return cell!
}
如果你想使用自定义单元格布局,我建议
子class
UITableViewCell
:// CustomTableViewCell.swift import UIKit class CustomTableViewCell: UITableViewCell { @IBOutlet weak var firstNameLabel: UILabel! @IBOutlet weak var lastNameLabel: UILabel! }
在故事板中创建 table 视图。将单元格原型添加到情节提要中的 table 视图。设计该单元格原型(添加您想要的任何标签)。
将单元格原型的故事板标识符指定为您想要的任何内容(在您的示例中为
MyCell
)。指定单元格原型的基数 class,在此示例中,
CustomTableViewCell
:在您的单元格原型和您的
之间连接UITableViewCell
子class.IBOutlet
引用注意
IBOutlet
参考左侧的实心项目符号。这表明插座已正确连接。在您的数据源中实施
cellForRowAtIndexPath
,例如在 Swift 3:func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "MyCell", for: indexPath) as! CustomTableViewCell let person = dataArray[indexPath.row] cell.firstNameLabel.text = person["firstName"] cell.lastNameLabel.text = person["lastName"] return cell }
或在Swift 2:
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCellWithIdentifier("MyCell", forIndexPath: indexPath) as! CustomTableViewCell let person = dataArray[indexPath.row] cell.firstNameLabel.text = person["firstName"] cell.lastNameLabel.text = person["lastName"] return cell }
请注意,如果使用单元格原型,您不会想要在
viewDidLoad
中调用registerClass
。 Storyboard 将自动为您使用重复使用的标识符注册您的自定义 class(因为您在步骤 3 和 4 中所做的)。
我所要做的就是:
cell.subviews[0].subviews[0].viewWithTag(//your tag//)