Sharad Chauhan
Sharad Chauhan

Reputation: 4891

navigate on click of collectionview cell inside tableview

I have a tableview cell inside which i have added collectionview cell ( for horizontal scrolling).

Now i want to push to other navigation controller on pressing any cell of horizontal collectionview. How to do it ? Or how can i define delegate methods for cell press.

Code :

ViewController.swift :

class ViewController: UIViewController {
    var categories = ["Action", "Drama", "Science Fiction", "Kids", "Horror"]
}

extension ViewController : UITableViewDelegate { }

extension ViewController : UITableViewDataSource {

    func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
        return categories[section]
    }

    func numberOfSections(in tableView: UITableView) -> Int {
        return categories.count
    }

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

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "cell") as! CategoryRow
        return cell
    }

}

CategoryRow.swift

class CategoryRow : UITableViewCell {
    @IBOutlet weak var collectionView: UICollectionView!
}

extension CategoryRow : UICollectionViewDataSource {

    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return 12
    }

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "videoCell", for: indexPath) as! VideoCell
        return cell
    }

}

extension CategoryRow : UICollectionViewDelegateFlowLayout {

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
        let itemsPerRow:CGFloat = 4
        let hardCodedPadding:CGFloat = 5
        let itemWidth = (collectionView.bounds.width / itemsPerRow) - hardCodedPadding
        let itemHeight = collectionView.bounds.height - (2 * hardCodedPadding)
        return CGSize(width: itemWidth, height: itemHeight)
    }

}

VideoCell.swift

class VideoCell : UICollectionViewCell {

    @IBOutlet weak var imageView: UIImageView!
}

Upvotes: 2

Views: 4009

Answers (4)

JeeVan TiWari
JeeVan TiWari

Reputation: 335

Make a protocol

protocol collectionViewCellClicked{
    func cellClicked()
}
  • Implement this protocol in main View Controller Your View Controller look like this

    class ViewController: UITableViewController, collectionViewCellClicked{ func cellClicked(){ // Your Code  }}
    
  • Your cellForRowAt delegate look like this

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: <#T##String#>, for: <#T##IndexPath#>) cell.delegate = self return cell }

  • In your Table View Cell Make a variable of type collectionViewCellClicked var delegate: collectionViewCellClicked?

    and in your didSelectItemAt delegate

    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { delegate.cellClicked() }

Upvotes: -1

Aravind A R
Aravind A R

Reputation: 2714

Here you will get the cell click at the delegate method didSelectItemAtIndexPath on CategoryRow class and from there you can fire a delegate to get call inside ViewController ViewController.swift :

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
            let cell = tableView.dequeueReusableCell(withIdentifier: "cell") as! CategoryRow
            cell.delegate = self
            return cell
        }

VideoCell.swift :

    protocol CategoryRowDelegate:class {
    func cellTapped()
    }

CategoryRow.swift :

    class CategoryRow : UITableViewCell {
         weak var delegate:CategoryRowDelegate?
        @IBOutlet weak var collectionView: UICollectionView!
    }

     func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
    if delegate!= nil {
    delegate?.cellTapped()
    }
    }

Add the delegate function inside ViewController

func cellTapped(){
//code for navigation
}

Upvotes: 7

Paresh Vasoya
Paresh Vasoya

Reputation: 53

First create protocol for delegation from CategoryRow.swift like below code

protocol CollectionViewSelectionDelegate: class {
    func didSelectedCollectionViewItem(selectedObject: AnyObject)
}

Now create delegate object on VideoCell.swift like below

weak var delegate:CollectionViewSelectionDelegate? 

Change ViewController.swift code before return cell

cell?.delegate = self

Override method of delegate in ViewController.swift and call similar method from VideoCell.swift from UICollectionView Delegate method.

Upvotes: 3

Amal T S
Amal T S

Reputation: 3415

I think its better to use Notification in this case.

post a notification in didSelectItem of collection view

NSNotificationCenter.defaultCenter().postNotificationName(notificationIdentifier, object: nil)

and add an observer in viewController viewDidLoad as follows

NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(pushToNew(_:)), name: notificationIdentifier, object: nil)

in the new pushToNew function, perform your segue

func pushToNew(notification: Notification) {
    // perform your segue here. Navigate to next view controller
}

Upvotes: 2

Related Questions