2

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!
}
Aravind A R
  • 2,674
  • 1
  • 15
  • 25
Sharad Chauhan
  • 4,821
  • 2
  • 25
  • 50

4 Answers4

7

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
}
Sharad Chauhan
  • 4,821
  • 2
  • 25
  • 50
Aravind A R
  • 2,674
  • 1
  • 15
  • 25
3

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.

2

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
}
Amal T S
  • 3,327
  • 2
  • 24
  • 57
  • 1 up for alternate solution. – Sharad Chauhan Jul 11 '17 at 09:34
  • also if possible tell me which will be more efficient ? using notification or delegate ? – Sharad Chauhan Jul 11 '17 at 09:37
  • 1
    We cant say which is more efficent. both do the functionality in your case. its simpler to use notifications when compared to delegates. Check this answer. It has more details about notifications & delegates https://stackoverflow.com/a/5325496/7456236 – Amal T S Jul 11 '17 at 09:43
-1

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() }

JeeVan TiWari
  • 325
  • 2
  • 15