如何通过协议和委托从 UITableViewCell 中的 UICollectionViewCell 传递数据以执行 segue 发件人?
how to pass data in perform segue sender through protocol & delegate from a UICollectionViewCell inside UITableViewCell?
- 我有 VC(a) 和 TableView
- 在UITableViewCell.xib里面我安装了一个UICollectionView
- UICollectionViewCell里面注册的UITableViewCell.xib
当然。
- 我想在 UICollectionViewCell didSelected
时执行从 VC(a) 到 VC(b) 的转场
- 而且由于 UICollectionViewCell 是在
UITableViewCell.xib 所以我不能使用 performSegue(withIdentifier:
String, sender: Any) 在 .xib 文件中,因为它不是
继承自 UIViewController
我在 Whosebug 中进行了一些搜索,我找到了通过创建自定义委托协议来执行 segue 的方法我应用了该协议,除了发件人之外一切似乎都正常!!
我知道如何在没有协议的情况下在VC中使用它,但我不知道在应用协议后如何使用它
我是 Swift 语言的新手,所以请帮助我完成我的代码
下面是UITableViewCell.xib代码
protocol MyCustomCellDelegator {
func cellWasPressed()
}
class AdminPList_TableViewCell: UITableViewCell {
var delegate: MyCustomCellDelegator?
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
setupCell()
getFProducts()
}
@IBOutlet weak var CollectionView: UICollectionView!
func getFProducts() {
productAPI.GetAllproducts { (appendThisProduct) in
self.FP_Array.append(appendThisProduct)
self.CollectionView.reloadData()
}
}
var FP_Array : [productObject] = []
}
extension AdminPList_TableViewCell : UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
func setupCell() {
CollectionView.delegate = self ; CollectionView.dataSource = self
CollectionView.register(UINib(nibName: "FproductsCell", bundle: nil), forCellWithReuseIdentifier: "FPcell")
// CollectionView.register(UINib(nibName: "TproductsCell", bundle: nil), forCellWithReuseIdentifier: "TPcell")
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: self.CollectionView.frame.size.width-10, height: self.CollectionView.frame.size.height)
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat { // make spacing between each cell
return 10
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return FP_Array.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let FPcell = CollectionView.dequeueReusableCell(withReuseIdentifier: "FPcell", for: indexPath) as! FproductsCell
FPcell.UpdateFP_cell_Content(RetrivedProducts: FP_Array[indexPath.row])
return FPcell
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let selectedProduct = FP_Array[indexPath.row] // I want to pass it to sender in perform segue un ProductsLibrary Class
// print (selectedProduct.productName)
self.delegate?.cellWasPressed()
}
}
帮我把 selectedProduct 传到下面的协议中执行 segue
下面是安装 UITableView 的VC(a):
class ProductsLibrary : UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
setupCell()
}
@IBOutlet weak var TableView: UITableView!
}
extension ProductsLibrary : UITableViewDelegate, UITableViewDataSource, MyCustomCellDelegator {
func cellWasPressed(withData: productObject) {
performSegue(withIdentifier: "EditProduct", sender: self)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let next = segue.destination as? ProductManagement{
print ("Editing Product is Active")
let product = sender as? productObject
print(product) //it shows nil !!!
next.EditingProduct = product
}
}
func setupCell() {
TableView.delegate = self ; TableView.dataSource = self
TableView.register(UINib(nibName: "AdminPList_TableViewCell", bundle: nil), forCellReuseIdentifier: "PLcell")
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 3
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "PLcell", for: indexPath) as! AdminPList_TableViewCell
cell.delegate = self
return cell
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return self.TableView.frame.size.height/3
}
}
你好吗?
也许你的 delegate 是 nil,这就是你 func callWasPressed() 没有调用的原因。
实例化单元后,您需要在 VC 上设置委托。
像这样:
AdminPList_TableViewCell.delegate = self
希望对你有所帮助!
编码愉快=D
当我开始学习 delegation 模式时,我总是犯一些错误。所以我给自己定了一个规则。当您必须实施委托时,请始终提醒 6 个步骤。
前 3 步是 class 将传递数据或写入协议 ,这里是你的 AdminPList_TableViewCell 就是 class。 3 个步骤是
- 写一个协议(一堆方法声明)//你做到了。
- 在 class 中声明一个将传递数据的协议变量。 // 你也这样做了 (var delegate: MyCustomCellDelegator?)
- 调用您声明的方法。 // 你做到了 (self.delegate?.cellWasPressed())
最后 3 个步骤是针对 class 的,它将符合该协议 ,这里 ProductsLibrary 是 class.
在将实现这些方法的 class 中遵守该协议。 // 这里你做了 (extension ProductsLibrary: ..., MyCustomCellDelegator)
将delegate赋值给self,但是这里的self是什么?好吧,self 就是被委托的 ProductsLibrary! // 你错过了
实现协议方法。 // 你做到了 :)
如何解决?
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
...
cell.delegate = self // you missed this line
...
return cell
}
现在通过 selectedProduct 只需更改各处的协议方法定义即可。
protocol MyCustomCellDelegator {
func cellWasPressed(withData: productObject)
}
然后从didSelectItemAt
方法调用
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let selectedProduct = FP_Array[indexPath.row] // I want to pass it to sender in perform segue un ProductsLibrary Class
self.delegate?.cellWasPressed(withData: selectedProduct)
}
现在在方法体内使用它。
func cellWasPressed(withData data: productObject) {
//now use the data and write your necessary code.
performSegue(withIdentifier: "EditProduct", sender: self)
}
希望对您有所帮助:).
要通过其他对象传递对象 VC 您需要执行以下 3 个步骤:
1st: 在你的新 VC 上创建一个 var:
var selectedObject: YourKindObject?
第二步:像这样将您的对象传递给发件人:
func cellWasPressed(withData data: productObject) {
// pass productObject as sender
performSegue(withIdentifier: "EditProduct", sender: productObject)}
3rd:在你的覆盖方法中,你应该捕获你的 segue ID 和 passthroug 对象,像这样:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "YourID(Can be setted on storyboard segue identifier))" {
var object = sender as! YourKindObject
let controller = segue.destination as? VC
controller?. selectedObject = object
}
}
- 我有 VC(a) 和 TableView
- 在UITableViewCell.xib里面我安装了一个UICollectionView
- UICollectionViewCell里面注册的UITableViewCell.xib 当然。
- 我想在 UICollectionViewCell didSelected 时执行从 VC(a) 到 VC(b) 的转场
- 而且由于 UICollectionViewCell 是在 UITableViewCell.xib 所以我不能使用 performSegue(withIdentifier: String, sender: Any) 在 .xib 文件中,因为它不是 继承自 UIViewController
我在 Whosebug 中进行了一些搜索,我找到了通过创建自定义委托协议来执行 segue 的方法我应用了该协议,除了发件人之外一切似乎都正常!!
我知道如何在没有协议的情况下在VC中使用它,但我不知道在应用协议后如何使用它
我是 Swift 语言的新手,所以请帮助我完成我的代码
下面是UITableViewCell.xib代码
protocol MyCustomCellDelegator {
func cellWasPressed()
}
class AdminPList_TableViewCell: UITableViewCell {
var delegate: MyCustomCellDelegator?
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
setupCell()
getFProducts()
}
@IBOutlet weak var CollectionView: UICollectionView!
func getFProducts() {
productAPI.GetAllproducts { (appendThisProduct) in
self.FP_Array.append(appendThisProduct)
self.CollectionView.reloadData()
}
}
var FP_Array : [productObject] = []
}
extension AdminPList_TableViewCell : UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
func setupCell() {
CollectionView.delegate = self ; CollectionView.dataSource = self
CollectionView.register(UINib(nibName: "FproductsCell", bundle: nil), forCellWithReuseIdentifier: "FPcell")
// CollectionView.register(UINib(nibName: "TproductsCell", bundle: nil), forCellWithReuseIdentifier: "TPcell")
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: self.CollectionView.frame.size.width-10, height: self.CollectionView.frame.size.height)
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat { // make spacing between each cell
return 10
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return FP_Array.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let FPcell = CollectionView.dequeueReusableCell(withReuseIdentifier: "FPcell", for: indexPath) as! FproductsCell
FPcell.UpdateFP_cell_Content(RetrivedProducts: FP_Array[indexPath.row])
return FPcell
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let selectedProduct = FP_Array[indexPath.row] // I want to pass it to sender in perform segue un ProductsLibrary Class
// print (selectedProduct.productName)
self.delegate?.cellWasPressed()
}
}
帮我把 selectedProduct 传到下面的协议中执行 segue
下面是安装 UITableView 的VC(a):
class ProductsLibrary : UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
setupCell()
}
@IBOutlet weak var TableView: UITableView!
}
extension ProductsLibrary : UITableViewDelegate, UITableViewDataSource, MyCustomCellDelegator {
func cellWasPressed(withData: productObject) {
performSegue(withIdentifier: "EditProduct", sender: self)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let next = segue.destination as? ProductManagement{
print ("Editing Product is Active")
let product = sender as? productObject
print(product) //it shows nil !!!
next.EditingProduct = product
}
}
func setupCell() {
TableView.delegate = self ; TableView.dataSource = self
TableView.register(UINib(nibName: "AdminPList_TableViewCell", bundle: nil), forCellReuseIdentifier: "PLcell")
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 3
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "PLcell", for: indexPath) as! AdminPList_TableViewCell
cell.delegate = self
return cell
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return self.TableView.frame.size.height/3
}
}
你好吗?
也许你的 delegate 是 nil,这就是你 func callWasPressed() 没有调用的原因。
实例化单元后,您需要在 VC 上设置委托。
像这样:
AdminPList_TableViewCell.delegate = self
希望对你有所帮助!
编码愉快=D
当我开始学习 delegation 模式时,我总是犯一些错误。所以我给自己定了一个规则。当您必须实施委托时,请始终提醒 6 个步骤。
前 3 步是 class 将传递数据或写入协议 ,这里是你的 AdminPList_TableViewCell 就是 class。 3 个步骤是
- 写一个协议(一堆方法声明)//你做到了。
- 在 class 中声明一个将传递数据的协议变量。 // 你也这样做了 (var delegate: MyCustomCellDelegator?)
- 调用您声明的方法。 // 你做到了 (self.delegate?.cellWasPressed())
最后 3 个步骤是针对 class 的,它将符合该协议 ,这里 ProductsLibrary 是 class.
在将实现这些方法的 class 中遵守该协议。 // 这里你做了 (extension ProductsLibrary: ..., MyCustomCellDelegator)
将delegate赋值给self,但是这里的self是什么?好吧,self 就是被委托的 ProductsLibrary! // 你错过了
实现协议方法。 // 你做到了 :)
如何解决?
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
...
cell.delegate = self // you missed this line
...
return cell
}
现在通过 selectedProduct 只需更改各处的协议方法定义即可。
protocol MyCustomCellDelegator {
func cellWasPressed(withData: productObject)
}
然后从didSelectItemAt
方法调用
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let selectedProduct = FP_Array[indexPath.row] // I want to pass it to sender in perform segue un ProductsLibrary Class
self.delegate?.cellWasPressed(withData: selectedProduct)
}
现在在方法体内使用它。
func cellWasPressed(withData data: productObject) {
//now use the data and write your necessary code.
performSegue(withIdentifier: "EditProduct", sender: self)
}
希望对您有所帮助:).
要通过其他对象传递对象 VC 您需要执行以下 3 个步骤:
1st: 在你的新 VC 上创建一个 var:
var selectedObject: YourKindObject?
第二步:像这样将您的对象传递给发件人:
func cellWasPressed(withData data: productObject) {
// pass productObject as sender
performSegue(withIdentifier: "EditProduct", sender: productObject)}
3rd:在你的覆盖方法中,你应该捕获你的 segue ID 和 passthroug 对象,像这样:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "YourID(Can be setted on storyboard segue identifier))" {
var object = sender as! YourKindObject
let controller = segue.destination as? VC
controller?. selectedObject = object
}
}