Sam
Sam

Reputation: 79

How to present a ViewController after pressing a button inside of a CollectionViewCell

Hey i'm new to programming and my problem is, i have a UICollectionViewController with 4 cells that are horizontal scrollable. Inside of the 4th cell i have a UIButton(optionsButton) on top of a UIView (ProfileContainerView).

The UIViewController I want to present is called ProfileEditViewController and is set up in Main.storyboard.

How can i present a UIViewController after pressing this button?

ProfileCell:

class ProfileCell: UICollectionViewCell {

    let profileContainerView: UIView = {
        let view = UIView()
        return view
    }()

    lazy var optionsButton: UIButton = {
        let btn = UIButton(type: .custom)
        btn.setImage(#imageLiteral(resourceName: "Settings"), for: UIControlState.normal)
        btn.addTarget(self, action: #selector(handleOptionsButton), for: UIControlEvents.touchUpInside)
        return btn
    }()

    @objc func handleOptionsButton() {
        print("Button pressed")
    }
}

HomeViewController:

class HomeViewController: UICollectionViewController, UICollectionViewDelegateFlowLayout {


    let profileCelId = "profileCell"

    override func viewDidLoad() {
        super.viewDidLoad()
        setupSwipeView()
    }


    func setupSwipeView() {
        collectionView?.register(UICollectionViewCell.self, forCellWithReuseIdentifier: cell)
        collectionView?.register(ProfileCell.self, forCellWithReuseIdentifier: profileCelId)        
    }


    override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {        
        if indexPath.item == 3 {
            return collectionView.dequeueReusableCell(withReuseIdentifier: profileCelId, for: indexPath)
        }
        return cell
    }
}

Upvotes: 0

Views: 886

Answers (3)

Sam
Sam

Reputation: 79

let proCell = ProfileCell()

override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: self.cell, for: indexPath)
    if indexPath.item == 3 {
        let profileCell = collectionView.dequeueReusableCell(withReuseIdentifier: profileCelId, for: indexPath)
        let button = proCell.optionsButton
            button.addTarget(self, action: #selector(handleOptionsButton), for: UIControlEvents.touchUpInside)
        return profileCell;
    }
    return cell
}

Upvotes: 0

Shuja Ud Din
Shuja Ud Din

Reputation: 434

You can use delegates to implement this.

Below is the code to implement this

 protocol ProfileCollectionViewCellDelegate {
 func buttonPressedAtIndexPath(inCell: ProfileCell)
 }

class ProfileCell: UICollectionViewCell {

var delegate : ProfileCollectionViewCellDelegate?
let profileContainerView: UIView = {
    let view = UIView()
    return view
}()

lazy var optionsButton: UIButton = {
    let btn = UIButton(type: .custom)
    btn.setImage(#imageLiteral(resourceName: "Settings"), for: UIControlState.normal)
    btn.addTarget(self, action: #selector(handleOptionsButton), for: UIControlEvents.touchUpInside)
    return btn
}()

@objc func handleOptionsButton() {
    if self.delegate != nil {
        self.delegate?.buttonPressedAtIndexPath(self)
    }
}
}

For your HomeViewController

 class HomeViewController: UICollectionViewController, UICollectionViewDelegateFlowLayout, ProfileCollectionViewCellDelegate  {


let profileCelId = "profileCell"

override func viewDidLoad() {
    super.viewDidLoad()
    setupSwipeView()
}


func setupSwipeView() {
    collectionView?.register(UICollectionViewCell.self, forCellWithReuseIdentifier: cell)
    collectionView?.register(ProfileCell.self, forCellWithReuseIdentifier: profileCelId)        
}


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

     let cell = collectionView.dequeueReusableCell(withReuseIdentifier: profileCelId, for: indexPath)
    cell.delegate = self
    return cell
 }

fun buttonPressedAtIndexPath(inCell: ProfileCell) {
       let indexOfCell = self.collectionView.indexPath(for: cell)
        if indexOfCell.row == 3 {
            //Do your work here
        }

}

}

Upvotes: 1

Lepidopteron
Lepidopteron

Reputation: 6165

You can present your ProfileEditViewController, which is styled in your Main.storyboard the following way:

1) Give your ProfileEditViewController a StoryBoard ID. E.g. "ProfileEditViewController" - Some question regarding this is here: What is a StoryBoard ID and how can i use this?

2) Register the UIViewController for the action on the UIButton or offer an appropriate callback functionality. As your HomeViewController is also your Collection View's datasource, you can easily extend your DataSource method

func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell`

Implementation could look like:

override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {        
    if indexPath.item == 3 {
        let profileCell = collectionView.dequeueReusableCell(withReuseIdentifier: profileCelId, for: indexPath)
        if let _cell = cell as? ProfileCell,
           let button = _cell.optionsButton as? UIButton {
            button.addTarget(self, action: #selector(handleOptionsButton), forControlEvents: UIControlEvents.TouchUpInside)
        }
        return profileCell;
    }
    return cell
}

Make sure that your buttons Action is now also being implemented by your HomeViewController

@objc func handleOptionsButton() {
    print("Button pressed")
}

3) Now in HomeViewController.handleOptionsButton you need to provide a functionality to support the transition to that specific Controller with the desired StoryboardID:

let storyboard = UIStoryboard(name: "Main", bundle:Bundle.main)
let controller = storyboard.instantiateViewController(withIdentifier: "ProfileEditViewController")
self.present(controller, animated: true, completion: nil)

Upvotes: 0

Related Questions