如何从代表的 collection 视图单元格中获取 indexPath 项目?
How to grab indexPath item from a collection view cell for a delegate?
我有一个 collection 视图,其中有一个部分 header。在该部分 header 我添加了另一个 collection 视图,显示推荐的配置文件供用户关注,并且它水平滚动。
我无法从 ReuseableView(包含第二个 collection 视图)推送视图控制器,因此我创建了一个协议,该协议将包含可以为我推送视图控制器的功能。
当我点击个人资料(单元格)时,它会将我推送到我自己的个人资料。因为我无法获取另一个 collection 视图中的 indexPath.item
。
协议
- 这里我创建了包含 func
HandleProfileTapped
的协议,名为 FeedReuseableView
的单元格是包含第二个 collection 视图的 sectionHeader 的名称。
protocol PeopleToFollowDelegate {
func handleProfileTapped(for cell: FeedReusableView)
}
推送用户的功能
- 这是我在提要文件中创建的函数,我将在 header 部分的委托中使用该函数。然而,这就是我的问题开始的地方。
// 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]()
是用户将在 header 部分看到的推荐配置文件。 如果 collection 视图不在 header 部分中,那么我会像这样轻松获取 indexPath
// 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)
}
总而言之,我只需要一种方法来获取 indexPath.item 以某种方式实现该功能。
编辑
这也是我在 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)
}
您可以在 header 部分中使用 collection 视图委托 didSelectItem,并通过使用以下代码。
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)
}
}
用例:UIApplication.topVC()?.pushVC(, animated: true)
按照@Abu Ul Hassan 的建议,您可以将 IndexPath 作为参数传递给您的协议函数,但在查看您的代码后,我发现您只需要选择索引,因此为简单起见,您可以通过以下方式执行此操作:
修改协议方法
protocol PeopleToFollowDelegate {
func handleProfileTapped(forIndex selectedIndex: Int)
}
从用户的 collectionView 的 didSelect 委托调用委托函数
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
peopleToFollowDelegate.handleProfileTapped(forIndex: indexPath.item)
}
然后像这样写handleProfileTapped函数:
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
}
您可以从
更改 didSelectRow 的实现
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
profilesTapped()
}
到
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
profilesTapped(user: peopleToFollow[indexPath.item])
}
这里是 profilesTapped 的实现
@objc func profilesTapped(user: User) {
delegate?.handleProfileTapped(for: user)
}
已编辑:
对于推送视图控制器,你应该这样做。如果我在使用 phone 时打错了内容,我深表歉意。
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)
}
我有一个 collection 视图,其中有一个部分 header。在该部分 header 我添加了另一个 collection 视图,显示推荐的配置文件供用户关注,并且它水平滚动。
我无法从 ReuseableView(包含第二个 collection 视图)推送视图控制器,因此我创建了一个协议,该协议将包含可以为我推送视图控制器的功能。
当我点击个人资料(单元格)时,它会将我推送到我自己的个人资料。因为我无法获取另一个 collection 视图中的 indexPath.item
。
协议
- 这里我创建了包含 func
HandleProfileTapped
的协议,名为FeedReuseableView
的单元格是包含第二个 collection 视图的 sectionHeader 的名称。
protocol PeopleToFollowDelegate {
func handleProfileTapped(for cell: FeedReusableView)
}
推送用户的功能
- 这是我在提要文件中创建的函数,我将在 header 部分的委托中使用该函数。然而,这就是我的问题开始的地方。
// 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]()
是用户将在 header 部分看到的推荐配置文件。 如果 collection 视图不在 header 部分中,那么我会像这样轻松获取 indexPath
// 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)
}
总而言之,我只需要一种方法来获取 indexPath.item 以某种方式实现该功能。
编辑
这也是我在 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)
}
您可以在 header 部分中使用 collection 视图委托 didSelectItem,并通过使用以下代码。
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)
}
}
用例:UIApplication.topVC()?.pushVC(, animated: true)
按照@Abu Ul Hassan 的建议,您可以将 IndexPath 作为参数传递给您的协议函数,但在查看您的代码后,我发现您只需要选择索引,因此为简单起见,您可以通过以下方式执行此操作:
修改协议方法
protocol PeopleToFollowDelegate { func handleProfileTapped(forIndex selectedIndex: Int) }
从用户的 collectionView 的 didSelect 委托调用委托函数
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { peopleToFollowDelegate.handleProfileTapped(forIndex: indexPath.item) }
然后像这样写handleProfileTapped函数:
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 }
您可以从
更改 didSelectRow 的实现func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
profilesTapped()
}
到
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
profilesTapped(user: peopleToFollow[indexPath.item])
}
这里是 profilesTapped 的实现
@objc func profilesTapped(user: User) {
delegate?.handleProfileTapped(for: user)
}
已编辑: 对于推送视图控制器,你应该这样做。如果我在使用 phone 时打错了内容,我深表歉意。
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)
}