如何在静态 table 视图上设置协议和委托?
How to setup protocols and delegates on a static table view?
我正在尝试设置一个静态 table 视图,该视图与另一个带有列表的 table 视图有连接。然后用户 select 从列表中选择一个项目,并更新主(静态)table 视图。我有设置代表,但我想我遗漏了一些东西。当 selecting 列表中的项目时,它会抛出异常 "unexpectedly finding 'nil' when force unwrapping optional"。看来可选的是协议本身。
Error Screenshot
Storyboard Diagram
主要Table查看文件
//
// AddAssetTableViewController.swift
// ItemizePro
//
// Created by Tyler Wasick on 5/27/20.
// Copyright © 2020 Tyler Wasick. All rights reserved.
//
import UIKit
class AddAssetTableViewController: UITableViewController {
// TODO: Add image IBOutlet
@IBOutlet weak var nameTextField: UITextField!
@IBOutlet weak var descriptionTextField: UITextField!
@IBOutlet weak var datePurchasedTextField: UITextField!
@IBOutlet weak var manufactureTextField: UITextField!
@IBOutlet weak var modelTextField: UITextField!
@IBOutlet weak var serialNumberTextField: UITextField!
@IBOutlet weak var costTextField: UITextField!
@IBOutlet weak var roomTextField: UITextField!
@IBOutlet weak var notesTextView: UITextView!
@IBOutlet weak var receiptTextField: UITextField!
@IBOutlet weak var addUIButton: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
// Uncomment the following line to preserve selection between presentations
// self.clearsSelectionOnViewWillAppear = false
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
// self.navigationItem.rightBarButtonItem = self.editButtonItem
}
// MARK: - Table view data source
/*
override func numberOfSections(in tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
return 0
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
return 0
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "imageCell", for: indexPath)
// Configure the cell...
return cell
}
*/
/*
// Override to support conditional editing of the table view.
override func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
// Return false if you do not want the specified item to be editable.
return true
}
*/
/*
// Override to support editing the table view.
override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == .delete {
// Delete the row from the data source
tableView.deleteRows(at: [indexPath], with: .fade)
} else if editingStyle == .insert {
// Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view
}
}
*/
/*
// Override to support rearranging the table view.
override func tableView(_ tableView: UITableView, moveRowAt fromIndexPath: IndexPath, to: IndexPath) {
}
*/
/*
// Override to support conditional rearranging of the table view.
override func tableView(_ tableView: UITableView, canMoveRowAt indexPath: IndexPath) -> Bool {
// Return false if you do not want the item to be re-orderable.
return true
}
*/
/*
// MARK: - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
// Get the new view controller using segue.destination.
// Pass the selected object to the new view controller.
}
*/
// MARK: - Functions
// MARK: - IBAction outlets
@IBAction func addButtonTapped(_ sender: UIButton) {
}
}
extension AddAssetTableViewController : RoomDelegate {
func tappedOnRoom(room: String) {
roomTextField.text = room
}
}
带有项目(房间)列表的
视图 select,它被传递回第一个 table 视图控制器
//
// RoomListViewController.swift
// ItemizePro
//
// Created by Tyler Wasick on 5/25/20.
// Copyright © 2020 Tyler Wasick. All rights reserved.
//
import UIKit
protocol RoomDelegate {
func tappedOnRoom(room: String)
}
class RoomListViewController : UIViewController {
var selectionDelegate : RoomDelegate!
@IBOutlet weak var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
// Configure table view
tableView.dataSource = self
tableView.delegate = self
}
// When user taps on a room, it returns the room to the delagate and dismisses
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
// Assign the selection to 'selectedRoom'
let selectedRoom = UserSettings.roomList[indexPath.row]
// Return the room to the delegate
selectionDelegate.tappedOnRoom(room: selectedRoom)
}
}
extension RoomListViewController: UITableViewDataSource, UITableViewDelegate {
// UITableViewDelegate
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return UserSettings.roomList.count
}
// UITableViewDataSource
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
// Setup cell
let cell = tableView.dequeueReusableCell(withIdentifier: "RoomListCell", for: indexPath) as! RoomListView
// Set the details for the cell
let room = UserSettings.roomList[indexPath.row]
cell.setRoomCell(room)
// Return the cell
return cell
}
}
崩溃是由于您使用了未为其提供值的强制解包委托。
绑定 Protocol
class:
这将允许您创建对委托的弱引用
protocol RoomDelegate: class {
func tappedOnRoom(room: String)
}
让你的代理变弱且可选:
weak var selectionDelegate: RoomDelegate?
在 AddAssetTableViewController 的 prepareForSegue
方法中设置委托。 这是您缺少的代码。
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let vc = segue.destination as? RoomListViewController {
vc.selectionDelegate = self
}
}
调用委托时使用可选链
selectionDelegate?.tappedOnRoom(room: selectedRoom)
我正在尝试设置一个静态 table 视图,该视图与另一个带有列表的 table 视图有连接。然后用户 select 从列表中选择一个项目,并更新主(静态)table 视图。我有设置代表,但我想我遗漏了一些东西。当 selecting 列表中的项目时,它会抛出异常 "unexpectedly finding 'nil' when force unwrapping optional"。看来可选的是协议本身。
Error Screenshot
Storyboard Diagram
主要Table查看文件
//
// AddAssetTableViewController.swift
// ItemizePro
//
// Created by Tyler Wasick on 5/27/20.
// Copyright © 2020 Tyler Wasick. All rights reserved.
//
import UIKit
class AddAssetTableViewController: UITableViewController {
// TODO: Add image IBOutlet
@IBOutlet weak var nameTextField: UITextField!
@IBOutlet weak var descriptionTextField: UITextField!
@IBOutlet weak var datePurchasedTextField: UITextField!
@IBOutlet weak var manufactureTextField: UITextField!
@IBOutlet weak var modelTextField: UITextField!
@IBOutlet weak var serialNumberTextField: UITextField!
@IBOutlet weak var costTextField: UITextField!
@IBOutlet weak var roomTextField: UITextField!
@IBOutlet weak var notesTextView: UITextView!
@IBOutlet weak var receiptTextField: UITextField!
@IBOutlet weak var addUIButton: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
// Uncomment the following line to preserve selection between presentations
// self.clearsSelectionOnViewWillAppear = false
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
// self.navigationItem.rightBarButtonItem = self.editButtonItem
}
// MARK: - Table view data source
/*
override func numberOfSections(in tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
return 0
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
return 0
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "imageCell", for: indexPath)
// Configure the cell...
return cell
}
*/
/*
// Override to support conditional editing of the table view.
override func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
// Return false if you do not want the specified item to be editable.
return true
}
*/
/*
// Override to support editing the table view.
override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == .delete {
// Delete the row from the data source
tableView.deleteRows(at: [indexPath], with: .fade)
} else if editingStyle == .insert {
// Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view
}
}
*/
/*
// Override to support rearranging the table view.
override func tableView(_ tableView: UITableView, moveRowAt fromIndexPath: IndexPath, to: IndexPath) {
}
*/
/*
// Override to support conditional rearranging of the table view.
override func tableView(_ tableView: UITableView, canMoveRowAt indexPath: IndexPath) -> Bool {
// Return false if you do not want the item to be re-orderable.
return true
}
*/
/*
// MARK: - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
// Get the new view controller using segue.destination.
// Pass the selected object to the new view controller.
}
*/
// MARK: - Functions
// MARK: - IBAction outlets
@IBAction func addButtonTapped(_ sender: UIButton) {
}
}
extension AddAssetTableViewController : RoomDelegate {
func tappedOnRoom(room: String) {
roomTextField.text = room
}
}
带有项目(房间)列表的
视图 select,它被传递回第一个 table 视图控制器
//
// RoomListViewController.swift
// ItemizePro
//
// Created by Tyler Wasick on 5/25/20.
// Copyright © 2020 Tyler Wasick. All rights reserved.
//
import UIKit
protocol RoomDelegate {
func tappedOnRoom(room: String)
}
class RoomListViewController : UIViewController {
var selectionDelegate : RoomDelegate!
@IBOutlet weak var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
// Configure table view
tableView.dataSource = self
tableView.delegate = self
}
// When user taps on a room, it returns the room to the delagate and dismisses
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
// Assign the selection to 'selectedRoom'
let selectedRoom = UserSettings.roomList[indexPath.row]
// Return the room to the delegate
selectionDelegate.tappedOnRoom(room: selectedRoom)
}
}
extension RoomListViewController: UITableViewDataSource, UITableViewDelegate {
// UITableViewDelegate
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return UserSettings.roomList.count
}
// UITableViewDataSource
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
// Setup cell
let cell = tableView.dequeueReusableCell(withIdentifier: "RoomListCell", for: indexPath) as! RoomListView
// Set the details for the cell
let room = UserSettings.roomList[indexPath.row]
cell.setRoomCell(room)
// Return the cell
return cell
}
}
崩溃是由于您使用了未为其提供值的强制解包委托。
绑定 Protocol
class:
这将允许您创建对委托的弱引用
protocol RoomDelegate: class {
func tappedOnRoom(room: String)
}
让你的代理变弱且可选:
weak var selectionDelegate: RoomDelegate?
在 AddAssetTableViewController 的 prepareForSegue
方法中设置委托。 这是您缺少的代码。
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let vc = segue.destination as? RoomListViewController {
vc.selectionDelegate = self
}
}
调用委托时使用可选链
selectionDelegate?.tappedOnRoom(room: selectedRoom)