Swift UITableView reloadData() 方法意外发现 nil 错误
Swift UITableView reloadData() method unexpectedly found nil error
我试图在 swift 中创建一个非常简单的待办事项列表应用程序,当我在 UITableView 上调用 reloadData 方法时,我收到此错误:“在隐式展开可选值时意外发现 nil”。当用户在来自 tableView 的单独视图控制器上的文本字段中键入内容后单击添加按钮时,我将调用此方法。他们键入的内容应该添加到 table 视图中,但它没有,我只是收到一个错误。
我上网查了一下,发现有人遇到了类似的问题,但我不知道如何将它们实现到我的代码中,或者不理解它们,因为我对 swift 还很陌生。我还尝试将文本字段放在与 table 视图相同的视图控制器上,这解决了问题,所以我猜它与此有关。
我的所有代码都在 ViewController.swift 中。这是:
import UIKit
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
@IBOutlet weak var tableView: UITableView!
@IBOutlet weak var editButton: UIBarButtonItem!
@IBOutlet weak var textField: UITextField!
var tableViewData = ["Apple", "Banana", "Orange", "Peach", "Pear"]
override func viewDidLoad() {
super.viewDidLoad()
}
// MARK: Tableview methods
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return tableViewData.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
cell.textLabel?.text = tableViewData[indexPath.row]
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
// print(tableViewData[indexPath.row])
}
// Allows reordering of cells
func tableView(_ tableView: UITableView, canMoveRowAt indexPath: IndexPath) -> Bool {
return true
}
// Handles reordering of cells
func tableView(_ tableView: UITableView, moveRowAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath) {
let item = tableViewData[sourceIndexPath.row]
tableViewData.remove(at: sourceIndexPath.row)
tableViewData.insert(item, at: destinationIndexPath.row)
}
// Allow the user to delete cells
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == UITableViewCell.EditingStyle.delete {
tableViewData.remove(at: indexPath.row)
tableView.reloadData()
}
}
// MARK: IBActions
@IBAction func edit(_ sender: Any) {
tableView.isEditing = tableView.isEditing
switch tableView.isEditing {
case true:
editButton.title = "Done"
case false:
editButton.title = "Edit"
}
}
@IBAction func add(_ sender: Any) {
let item: String = textField.text!
tableViewData.append(item)
textField.text = ""
tableView.reloadData() // <------ **This line gives me the error**
}
}
此外,我尝试在出现错误的行上使用可选链接,写 tableView?.reloadData()
。它使错误消失,但 none 的项目被添加到 table 视图。
不确定是否有必要,但这是故事板的图像,因此您可以看到所有屏幕
抱歉,如果这是一个非常明显的问题。就像我说的那样,我对 swift 和 iOS 应用程序总体上还很陌生。
提前致谢!
您似乎正在将 ViewController
class 分配给您的第一个控制器(包含 table 视图)AND 到您的第二个控制器(带有文本字段)。
那是行不通的。
将此 class 添加到您的项目中,将其指定为“新项目”视图控制器的自定义 Class,然后连接 @IBOutlet
和 @IBAction
:
class NewItemViewController: UIViewController {
// callback closure to tell the VC holding the table view
// that the Add button was tapped, and to
// "send back" the new text
var callback: ((String) -> ())?
@IBOutlet weak var textField: UITextField!
@IBAction func add(_ sender: Any) {
let item: String = textField.text!
callback?(item)
textField.text = ""
}
}
接下来,将您的 ViewController
class 更改为以下内容:
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
@IBOutlet weak var tableView: UITableView!
@IBOutlet weak var editButton: UIBarButtonItem!
var tableViewData = ["Apple", "Banana", "Orange", "Peach", "Pear"]
override func viewDidLoad() {
super.viewDidLoad()
// if you're not already seeing "Apple", "Banana", "Orange", "Peach", "Pear"
// add these two lines
//tableView.dataSource = self
//tableView.delegate = self
}
// MARK: Tableview methods
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return tableViewData.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
cell.textLabel?.text = tableViewData[indexPath.row]
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
// print(tableViewData[indexPath.row])
}
// Allows reordering of cells
func tableView(_ tableView: UITableView, canMoveRowAt indexPath: IndexPath) -> Bool {
return true
}
// Handles reordering of cells
func tableView(_ tableView: UITableView, moveRowAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath) {
let item = tableViewData[sourceIndexPath.row]
tableViewData.remove(at: sourceIndexPath.row)
tableViewData.insert(item, at: destinationIndexPath.row)
}
// Allow the user to delete cells
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == UITableViewCell.EditingStyle.delete {
tableViewData.remove(at: indexPath.row)
tableView.reloadData()
}
}
// MARK: IBActions
@IBAction func edit(_ sender: Any) {
tableView.isEditing = !tableView.isEditing
switch tableView.isEditing {
case true:
editButton.title = "Done"
case false:
editButton.title = "Edit"
}
}
// when "New Item" button is tapped, it will segue to
// NewItemViewController... set the callback closure here
// prepare for segue is called when you have created a segue to another view controller
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
// error checking is always a good idea
// this properly unwraps the destination controller and confirms it's
// an instance of NewItemViewController
if let vc = segue.destination as? NewItemViewController {
// callback is a property we added to NewItemViewController
// we declared it to return a String
vc.callback = { item in
self.tableViewData.append(item)
self.tableView.reloadData()
self.navigationController?.popViewController(animated: true)
}
}
}
}
当您点击“添加项目”按钮时,我们假设您已经连接到“新项目”视图控制器。通过实施:
override func prepare(for segue: UIStoryboardSegue, sender: Any?)
我们将获得对即将出现的“新项目”视图控制器的引用,我们将为其分配一个“回调闭包”。
当我们输入一些文本并点击下一个控制器中的“添加”按钮时,它将“回调”到第一个控制器,传递新输入的文本。 是我们更新数据数组的地方,重新加载 table,然后弹出导航堆栈。
我试图在 swift 中创建一个非常简单的待办事项列表应用程序,当我在 UITableView 上调用 reloadData 方法时,我收到此错误:“在隐式展开可选值时意外发现 nil”。当用户在来自 tableView 的单独视图控制器上的文本字段中键入内容后单击添加按钮时,我将调用此方法。他们键入的内容应该添加到 table 视图中,但它没有,我只是收到一个错误。
我上网查了一下,发现有人遇到了类似的问题,但我不知道如何将它们实现到我的代码中,或者不理解它们,因为我对 swift 还很陌生。我还尝试将文本字段放在与 table 视图相同的视图控制器上,这解决了问题,所以我猜它与此有关。
我的所有代码都在 ViewController.swift 中。这是:
import UIKit
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
@IBOutlet weak var tableView: UITableView!
@IBOutlet weak var editButton: UIBarButtonItem!
@IBOutlet weak var textField: UITextField!
var tableViewData = ["Apple", "Banana", "Orange", "Peach", "Pear"]
override func viewDidLoad() {
super.viewDidLoad()
}
// MARK: Tableview methods
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return tableViewData.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
cell.textLabel?.text = tableViewData[indexPath.row]
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
// print(tableViewData[indexPath.row])
}
// Allows reordering of cells
func tableView(_ tableView: UITableView, canMoveRowAt indexPath: IndexPath) -> Bool {
return true
}
// Handles reordering of cells
func tableView(_ tableView: UITableView, moveRowAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath) {
let item = tableViewData[sourceIndexPath.row]
tableViewData.remove(at: sourceIndexPath.row)
tableViewData.insert(item, at: destinationIndexPath.row)
}
// Allow the user to delete cells
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == UITableViewCell.EditingStyle.delete {
tableViewData.remove(at: indexPath.row)
tableView.reloadData()
}
}
// MARK: IBActions
@IBAction func edit(_ sender: Any) {
tableView.isEditing = tableView.isEditing
switch tableView.isEditing {
case true:
editButton.title = "Done"
case false:
editButton.title = "Edit"
}
}
@IBAction func add(_ sender: Any) {
let item: String = textField.text!
tableViewData.append(item)
textField.text = ""
tableView.reloadData() // <------ **This line gives me the error**
}
}
此外,我尝试在出现错误的行上使用可选链接,写 tableView?.reloadData()
。它使错误消失,但 none 的项目被添加到 table 视图。
不确定是否有必要,但这是故事板的图像,因此您可以看到所有屏幕
抱歉,如果这是一个非常明显的问题。就像我说的那样,我对 swift 和 iOS 应用程序总体上还很陌生。
提前致谢!
您似乎正在将 ViewController
class 分配给您的第一个控制器(包含 table 视图)AND 到您的第二个控制器(带有文本字段)。
那是行不通的。
将此 class 添加到您的项目中,将其指定为“新项目”视图控制器的自定义 Class,然后连接 @IBOutlet
和 @IBAction
:
class NewItemViewController: UIViewController {
// callback closure to tell the VC holding the table view
// that the Add button was tapped, and to
// "send back" the new text
var callback: ((String) -> ())?
@IBOutlet weak var textField: UITextField!
@IBAction func add(_ sender: Any) {
let item: String = textField.text!
callback?(item)
textField.text = ""
}
}
接下来,将您的 ViewController
class 更改为以下内容:
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
@IBOutlet weak var tableView: UITableView!
@IBOutlet weak var editButton: UIBarButtonItem!
var tableViewData = ["Apple", "Banana", "Orange", "Peach", "Pear"]
override func viewDidLoad() {
super.viewDidLoad()
// if you're not already seeing "Apple", "Banana", "Orange", "Peach", "Pear"
// add these two lines
//tableView.dataSource = self
//tableView.delegate = self
}
// MARK: Tableview methods
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return tableViewData.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
cell.textLabel?.text = tableViewData[indexPath.row]
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
// print(tableViewData[indexPath.row])
}
// Allows reordering of cells
func tableView(_ tableView: UITableView, canMoveRowAt indexPath: IndexPath) -> Bool {
return true
}
// Handles reordering of cells
func tableView(_ tableView: UITableView, moveRowAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath) {
let item = tableViewData[sourceIndexPath.row]
tableViewData.remove(at: sourceIndexPath.row)
tableViewData.insert(item, at: destinationIndexPath.row)
}
// Allow the user to delete cells
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == UITableViewCell.EditingStyle.delete {
tableViewData.remove(at: indexPath.row)
tableView.reloadData()
}
}
// MARK: IBActions
@IBAction func edit(_ sender: Any) {
tableView.isEditing = !tableView.isEditing
switch tableView.isEditing {
case true:
editButton.title = "Done"
case false:
editButton.title = "Edit"
}
}
// when "New Item" button is tapped, it will segue to
// NewItemViewController... set the callback closure here
// prepare for segue is called when you have created a segue to another view controller
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
// error checking is always a good idea
// this properly unwraps the destination controller and confirms it's
// an instance of NewItemViewController
if let vc = segue.destination as? NewItemViewController {
// callback is a property we added to NewItemViewController
// we declared it to return a String
vc.callback = { item in
self.tableViewData.append(item)
self.tableView.reloadData()
self.navigationController?.popViewController(animated: true)
}
}
}
}
当您点击“添加项目”按钮时,我们假设您已经连接到“新项目”视图控制器。通过实施:
override func prepare(for segue: UIStoryboardSegue, sender: Any?)
我们将获得对即将出现的“新项目”视图控制器的引用,我们将为其分配一个“回调闭包”。
当我们输入一些文本并点击下一个控制器中的“添加”按钮时,它将“回调”到第一个控制器,传递新输入的文本。 是我们更新数据数组的地方,重新加载 table,然后弹出导航堆栈。