Reputation: 387
I have a collectionView that has a section header. In that section header I've added another collectionView that displays recommended profiles for users to follow, and it scrolls horizontal.
I cannot push view controllers from a ReuseableView ( that holds the second collection view), so I created a protocol that will hold a function that can push the view controller for me.
When I tap a profile (cell) it pushes me to my own profile. Because I cannot grab the indexPath.item
that is in another collectionView.
Protocol
HandleProfileTapped
,the cell named FeedReuseableView
is the name of the sectionHeader that holds the second collection view.protocol PeopleToFollowDelegate {
func handleProfileTapped(for cell: FeedReusableView)
}
Function to push user
// Create function to push users to the correct profile when selected
func handleProfileTapped(for header: FeedReusableView) {
print("profile tapped, push user to the correct profile page")
let header = FeedReusableView()
//try to grab the indexpath item so the corrext data is pushed
let user = header.peopleToFollow // ??? What goes here? I cannot grab index path
let storyBoard : UIStoryboard = UIStoryboard(name: "Main", bundle:nil)
let profileViewController = storyBoard.instantiateViewController(withIdentifier: "profileViewController") as? ProfileViewController
profileViewController?.user? = user
self.navigationController?.pushViewController(profileViewController!, animated: true)
}
peopleToFollow = [User]()
is the recommended profiles users will see in the section header. IF the collection view was not in a section header, then I would easily grab the indexPath like this // When profile is tapped, push user to userProfile
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let user = peopleToFollow[indexPath.item]
let storyBoard : UIStoryboard = UIStoryboard(name: "Main", bundle:nil)
let profileViewController = storyBoard.instantiateViewController(withIdentifier: "profileViewController") as? ProfileViewController
profileViewController?.user = user
// Then push to next controller ( profile)
}
To sum it up, I just need a way to grab the indexPath.item somehow for that func.
Edit
Here is also were I use the function in the FeedReuseableView
var delegate: PeopleToFollowDelegate?
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
// Return the number of profiles
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return peopleToFollow.count
}
//Display the recommended profiles
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "profilesCell", for: indexPath) as! PeopleToFollowCollectionCell
cell.user = peopleToFollow[indexPath.item]
return cell
}
// When profile is tapped, push user to userProfile
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
profilesTapped()
}
@objc func profilesTapped() {
delegate?.handleProfileTapped(for: self)
}
Upvotes: 1
Views: 958
Reputation: 1845
you can change the implementation of didSelectRow from
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
profilesTapped()
}
to
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
profilesTapped(user: peopleToFollow[indexPath.item])
}
Here is the implementation of profilesTapped
@objc func profilesTapped(user: User) {
delegate?.handleProfileTapped(for: user)
}
Edited: For pushing view controller you should do this. Apologies if I typed something wrong as I am using my phone now.
func handleProfileTapped(for user: User) {
let storyBoard : UIStoryboard = UIStoryboard(name: "Main", bundle:nil)
if let profileViewController = storyBoard.instantiateViewController(withIdentifier: "profileViewController") as? ProfileViewController {
profileViewController.user = user
self.navigationController?.pushViewController(profileViewController, animated: true)
}
Upvotes: 3
Reputation: 145
As suggested by @Abu Ul Hassan you can pass IndexPath as a argument to your protocol function but after reviewing your code I observed that only thing you need is selected index therefore for simplicity you can do this in following way:
Modify your protocol method
protocol PeopleToFollowDelegate {
func handleProfileTapped(forIndex selectedIndex: Int)
}
Call delegate function from User's collectionView's didSelect delegate
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
peopleToFollowDelegate.handleProfileTapped(forIndex: indexPath.item)
}
Then write handleProfileTapped function like this:
func handleProfileTapped(forIndex selectedIndex: Int) {
let user = peopleToFollow[selectedIndex]
let storyBoard : UIStoryboard = UIStoryboard(name: "Main", bundle:nil)
let profileViewController = storyBoard.instantiateViewController(withIdentifier:"profileViewController") as? ProfileViewController
profileViewController?.user = user
// Then push to next controller
}
Upvotes: 1
Reputation: 388
You can use collection view delegate didSelectItem inside section header and directly push to profile viewcontroller from section reusable view by accessing topMost viewcontroller in navigation stack by using following code.
extension UIApplication {
class func topVC(controller: UIViewController? = UIApplication.shared.keyWindow?.rootViewController) -> UIViewController? {
if let navigationController = controller as? UINavigationController {
return topVC(controller: navigationController.visibleViewController)
}
if let tabController = controller as? UITabBarController {
if let selected = tabController.selectedViewController {
return topVC(controller: selected)
}
}
if let presented = controller?.presentedViewController {
return topVC(controller: presented)
}
return controller
}
}
extension UIViewController {
func pushVC(_ vc: UIViewController, animated: Bool = true) {
navigationController?.pushViewController(vc, animated: animated)
}
}
Use case: UIApplication.topVC()?.pushVC(, animated: true)
Upvotes: 0