在嵌入在 UITableviewCell 中的 UICollectionView 中进行 Segue,Swift

Posted

技术标签:

【中文标题】在嵌入在 UITableviewCell 中的 UICollectionView 中进行 Segue,Swift【英文标题】:Segue in a UICollectionView embedded in a UITableviewCell, Swift 【发布时间】:2017-09-25 08:29:50 【问题描述】:

我在UITableViewCell 中创建了一个UICollectionView,效果很好。我唯一的问题是,我无法在 didSelectItemAt 方法上对另一个 ViewController 执行 Segue。

我知道我必须从 TableViewController 执行它,我在 Storyboard 上做了一个 segue,我尝试了多种可能性,但由于某些原因它不起作用。

这里是我的TableviewController

import UIKit
import RealmSwift
import SwiftyJSON

class HomeVTwoTableViewController: UITableViewController 

let realm = try! Realm()
let headers = ["1","2","3"]

override func viewDidLoad() 
    super.viewDidLoad()


override func viewWillAppear(_ animated: Bool)     
    self.tableView.separatorStyle = .none



//MARK: Custom Tableview Headers
override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? 
    return headers[section]


//MARK: DataSource Methods
override func numberOfSections(in tableView: UITableView) -> Int 
    return headers.count


override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int 
    return 1


//Choosing the responsible PrototypCell for the Sections
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell 
    if indexPath.section == 0 
        let cell = tableView.dequeueReusableCell(withIdentifier: "cellBig", for: indexPath) as! HomeVTwoTableViewCell
        cell.update()
        return cell
     else 
        return UITableViewCell()
    

// This on of my tries to perform a segue
func liveCellSelected() 
    performSegue(withIdentifier: "showChat", sender: nil)


这里是我的TableViewCell 和嵌入的CollectionView

import UIKit
import RealmSwift



class HomeVTwoTableViewCell: UITableViewCell

var liveCommunities: Results<Community>?

@IBOutlet weak var collectionView: UICollectionView!

override func awakeFromNib() 
    super.awakeFromNib()
    collectionView.delegate = self
    collectionView.dataSource = self



extension HomeVTwoTableViewCell: 
UICollectionViewDataSource,UICollectionViewDelegate 

func numberOfSections(in collectionView: UICollectionView) -> Int

    return 1


func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int

    return(liveCommunities?.count)!


func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell

    guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "collectionCellBig", for: indexPath) as? HomeVTwoCollectionViewCell else
    
        fatalError("Cell has wrong type")
    
    //removes the old image
    cell.imageView.image = UIImage(named: "No Image")
    cell.titleLbl.text = nil

    //set url and Picture
    url = (liveCommunities?[indexPath.row].pictureId)!
    let name : String = (liveCommunities?[indexPath.row].communityName)!
    let channelName : String = (liveCommunities?[indexPath.row].channelName)!

    cell.titleLbl.text = name
    cell.senderLbl.text = channelName
    cell.imageView.downloadedFrom(link :"someSecretUrl")

    return cell


func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) 
    selectedCommunity = (liveCommunities?[indexPath.row].communityId)!
    HomeVTwoTableViewController().liveCellSelected()


我发现another question 具有类似的主题,但无法实现委托协议而不会对现有委托产生问题。

也许这是一个明显的错误,但我看不到。 提前致谢。

【问题讨论】:

【参考方案1】:

你正在用这个实例化你的家庭控制器的一个新实例:

func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) 
    selectedCommunity = (liveCommunities?[indexPath.row].communityId)!
    HomeVTwoTableViewController().liveCellSelected()

你应该做的是通过委托来实现,或者你将你的collectionview委托移动到主控制器

protocol CellCollectionViewDelegate: class
  func didselect()

然后你在单元格和你的家庭控制器中实现委托

【讨论】:

感谢您的回答。在问这个问题之前,我实际上尝试过这个。我这样尝试:protocol CellCollectionViewDelegate: class func didSelect() 并定义了在 didselect 中调用它的变量weak var delegate: CellCollectionViewDelegate?,并在控制器中进行了这样的扩展:extension HomeVTwoTableViewController: CellCollectionViewDelegate func didSelect() performSegue(withIdentifier: "showChat", sender: nil) 但它不起作用。也许你可以帮助我。 你必须在 cellforrow 函数中设置 delegate = self 感谢您的回答。我有 CollectionView.delegate = self 并且如果不弄乱第一个就无法实现另一个。 我的意思是 cell.delegate 不是 collectionview 委托【参考方案2】:

也许你可以创建一个变量来处理这个问题。你也可以做可选的。

class HomeVTwoTableViewCell: UITableViewCell
var liveCommunities: Results<Community>?
@IBOutlet weak var collectionView: UICollectionView!
var didSelectAction: () -> Void // add your action here

这里可以调用这个函数

func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) 
    selectedCommunity = (liveCommunities?[indexPath.row].communityId)!
    HomeVTwoTableViewController().liveCellSelected()
    didSelectAction() // Invoque your action

//在单元格创建器上,添加要点击单元格时的导航或逻辑

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell 
    if indexPath.section == 0 
        let cell = tableView.dequeueReusableCell(withIdentifier: "cellBig", for: indexPath) as! HomeVTwoTableViewCell
        cell.update()
        cell.didSelectAction = 
           // add here your navigation
        
        return cell
     else 
        return UITableViewCell()
    

【讨论】:

感谢您的回复。但是,如果我尝试您的方法,我会收到“Class 'HomeVTwoTableViewCell' has no initializers”错误。 解决这个问题...您可以将其设为可选或分配空函数 var didSelectAction: (() -> Void ) ?或 var didSelectAction: () -> Void = 谢谢,现在它可以工作了。但这是最好的解决方案吗?它似乎有点复杂?你怎么看? 委托模式可能更容易【参考方案3】:

好吧,这个问题似乎有两个解决方案。 一种是通过变量,一种是通过委托。据我所知,委托更常见。

带变量的解决方案 1:

这里是我的TableviewController

import UIKit

class TableViewController: UITableViewController 

let headers = ["1","2","3"]

override func viewDidLoad() 
    super.viewDidLoad()


override func numberOfSections(in tableView: UITableView) -> Int 
    return headers.count


override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int 
    return 1


override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell 
        let cell = tableView.dequeueReusableCell(withIdentifier: "cellBig", for: indexPath) as! HomeVTwoTableViewCell
  //Fill function, insert Navigation      
  cell.didSelectAction = 
            self.performSegue(withIdentifier: "testSegue", sender: nil)
        
        return cell

这里是我的TableViewCell 和嵌入的CollectionView

import UIKit

class HomeVTwoTableViewCell: UITableViewCell

var liveCommunities: Results<Community>?
//Instantiate function
var didSelectAction: () -> Void = 

@IBOutlet weak var collectionView: UICollectionView!

override func awakeFromNib() 
    super.awakeFromNib()
    collectionView.delegate = self
    collectionView.dataSource = self



extension HomeVTwoTableViewCell: 
UICollectionViewDataSource,UICollectionViewDelegate 

func numberOfSections(in collectionView: UICollectionView) -> Int

    return 1


func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int

    return(liveCommunities?.count)!


func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell

    guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "collectionCellBig", for: indexPath) as? HomeVTwoCollectionViewCell else
    
        fatalError("Cell has wrong type")
    
    //removes the old text
    cell.titleLbl.text = nil
    cell.senderLbl.text = nil

    let name : String = (liveCommunities?[indexPath.row].communityName)!
    let channelName : String = (liveCommunities?[indexPath.row].channelName)!

    cell.titleLbl.text = name
    cell.senderLbl.text = channelName

    return cell


func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) 
    selectedCommunity = (liveCommunities?[indexPath.row].communityId)!
  // Invoque your action 
  didSelectAction()


使用委托和协议的解决方案 2:

这里是我的TableviewController

import UIKit

class TableViewController: UITableViewController 

let headers = ["1","2","3"]

override func viewDidLoad() 
    super.viewDidLoad()


override func numberOfSections(in tableView: UITableView) -> Int 
    return headers.count


override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int 
    return 1


override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell 
        let cell = tableView.dequeueReusableCell(withIdentifier: "cellBig", for: indexPath) as! HomeVTwoTableViewCell
  //Add delegate      
  cell.delegate = self
  return cell

 //Add Extension with Navigation
 extension HomeVTwoTableViewController: CellCollectionViewDelegate 
     func didSelect() 
         performSegue(withIdentifier: "showChat", sender: nil)
    

这里是我的TableViewCell 和嵌入的CollectionView

import UIKit
//Create a delegate protocol
protocol CellCollectionViewDelegate: class
func didSelect()


class HomeVTwoTableViewCell: UITableViewCell

var liveCommunities: Results<Community>?
//Add a delegate property
weak var delegate: CellCollectionViewDelegate?

@IBOutlet weak var collectionView: UICollectionView!

override func awakeFromNib() 
    super.awakeFromNib()
    collectionView.delegate = self
    collectionView.dataSource = self


//Adopt and implement the Delegate Protocol
extension HomeVTwoTableViewCell: 
UICollectionViewDataSource,UICollectionViewDelegate 

func numberOfSections(in collectionView: UICollectionView) -> Int

    return 1


func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int

    return(liveCommunities?.count)!


func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell

    guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "collectionCellBig", for: indexPath) as? HomeVTwoCollectionViewCell else
    
        fatalError("Cell has wrong type")
    
    //removes the old text
    cell.titleLbl.text = nil
    cell.senderLbl.text = nil

    let name : String = (liveCommunities?[indexPath.row].communityName)!
    let channelName : String = (liveCommunities?[indexPath.row].channelName)!

    cell.titleLbl.text = name
    cell.senderLbl.text = channelName

    return cell


func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) 
    selectedCommunity = (liveCommunities?[indexPath.row].communityId)!
    //call delegate method
    delegate?.didSelect()


我试图总结来自

的解决方案

Abdoelrhman Mohamed 和 Alexkater 并详细写出来。

如果有问题或遗漏,请告诉我。

【讨论】:

以上是关于在嵌入在 UITableviewCell 中的 UICollectionView 中进行 Segue,Swift的主要内容,如果未能解决你的问题,请参考以下文章

在嵌入在 UITableviewCell 中的 UICollectionView 中进行 Segue,Swift

嵌入在 UITableViewCell 中的动态、自定义布局 UICollectionView

如何为嵌入在 UITableViewCell 中的 UIView 设置动画

如何从嵌入在 UITableViewCell (Swift) 中的 UICollectionView 的单元格中分离出来?

iOS/Swift:UITableViewCell 中的两个嵌入式视图在运行时未出现

UITableViewCell 具有嵌入式垂直堆栈视图设置,具有自动布局和动态高度