Swift:如何在 UITableViewController(包含 UICollectionView)中使用“didSelectItemAtIndexPath”?

Posted

技术标签:

【中文标题】Swift:如何在 UITableViewController(包含 UICollectionView)中使用“didSelectItemAtIndexPath”?【英文标题】:Swift: How to use "didSelectItemAtIndexPath" in UITableViewController(contains UICollectionView)? 【发布时间】:2016-08-19 02:39:15 【问题描述】:

我有一个UITableViewController,在TableViewCell 里面,它是一个UICollectionView。当用户点击单元格时,我想将数据从CollectionViewCell 传递给DetailViewController。我将一个segue从CollectionViewCell拖到DetailViewController,并在TableViewCell(包含CollectionView)中使用了didSelectItemAtIndexPath,它可以工作。

class TableViewCell: UITableViewCell, UICollectionViewDataSource, UICollectionViewDelegate 

var posts1: [Posts] = [Posts]()
var posts2: [Posts] = [Posts]()
var categories: [Category] = [Category]()
var selectedPost1: Posts?

@IBOutlet weak var theCollectionView: UICollectionView!


func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int 
    return posts1.count



func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell 
    let collectionViewCell = collectionView.dequeueReusableCellWithReuseIdentifier("CollectionViewCell", forIndexPath: indexPath) as! CollectionViewCell

        let imageUrlString: String = posts1[indexPath.row].postThumbnailUrlString
        let imageUrl: NSURL = NSURL(string: imageUrlString)!
    //Give Images A round cornor

    let filter = AspectScaledToFillSizeWithRoundedCornersFilter(
        size: collectionViewCell.postImageView.frame.size,
        radius: 20.0
    )

    collectionViewCell.postImageView.af_setImageWithURL(imageUrl, filter: filter)

    collectionViewCell.postTitleLabel.text = posts1[indexPath.row].postTite
return collectionViewCell


func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) 
    print("selected")
    self.selectedPost1 = self.posts1[indexPath.row]

可以打印"selected",表示数据已经存入self.selectedPost1。但是我不能在这个类中使用prepareForSegue,因为它只能在ViewController中使用。有人告诉我在我的HomeTableViewController 中实现UICollectionViewDelegate,并在HomeTableViewController 中调用函数didSelectedItemAtIndexPath,如下所示:

import UIKit

class HomePageTableViewController: UITableViewController,UICollectionViewDelegate 
    let sections: NSArray = ["latest news", "good news"]
    var posts1: [Posts] = [Posts]()
    var selectedIndexPath: NSIndexPath?

override func viewDidLoad() 
    super.viewDidLoad()




override func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String? 
  if section < sections.count
        return sections[section] as? String
    

    return nil



override func numberOfSectionsInTableView(tableView: UITableView) -> Int 
    return sections.count


override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int 

    return 1

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell 

    if indexPath.row == 0 && indexPath.section == 0 
        let tableViewCell = tableView.dequeueReusableCellWithIdentifier("TableViewCell") as! TableViewCell

        tableViewCell.getCategories()
     //   tableViewCell.scrollToNextCell()
     //   tableViewCell.startTimer()


        return tableViewCell

    
func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) 
    self.performSegueWithIdentifier("goToDetail", sender: TableViewCell())
    print("selected")


override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) 
    if let tableViewCell1 = sender as? TableViewCell,
    let postDetailPage = segue.destinationViewController as? DetailViewController

        let selectedPosts = tableViewCell1.selectedPost1

        postDetailPage.selectedPost?.selectedPost1 = selectedPosts


但是,didSelectedItemAtIndexPath 不能被调用,没有打印。我不知道为什么?

这是我的DetailViewController

import UIKit

class DetailViewController: UIViewController 
@IBOutlet weak var postImageView: UIImageView!

var posts: [Posts] = [Posts]()
var selectedPost: TableViewCell?

override func viewDidLoad() 
    super.viewDidLoad()

    if let post = selectedPost?.selectedPost1
        let thumbnailUrlString = post.postThumbnailUrlString
        let imageUrl: NSURL = NSURL(string: thumbnailUrlString)!
        print(thumbnailUrlString)
        postImageView.af_setImageWithURL(imageUrl)
    

我还需要在viewDidLoadviewDidAppear 中实现吗?

我在这个问题上挣扎了几天?需要一些关于如何从UICollectionViewCell(在UITableViewCell 中)到新UIViewController 的建议。

【问题讨论】:

对于didSelectRowAtIndexPath 中的collectionview,删除segue 并在它打印“selected”时更新我 我删除了Segue,点击单元格后仍然可以打印“selected” 我建议您参考this github code,它具有您需要的相同实现。尽管在您的代码中,您需要使用cell.objectOfCollectionviewcellForRowAtIndexPath 中设置UICollectionView 委托。 好的,我去看看,@DipenPanchasara。因为我是swift新手,还有很多东西不明白.. 它是用objective-c写的,我不是很熟悉,我开始用swift学习ios开发。@DipenPanchasara 【参考方案1】:

你走的路是正确的,但你犯了一个错误。尝试在TableViewCell中实现UICollectionViewDelegate方法didSelectItemAtIndexPath并将其从HomePageTableViewController中删除。

现在声明一个协议,然后在TableViewCell 中创建它的实例并在HomePageTableViewController 中实现该协议,然后在didSelectItemAtIndexPath 中使用该委托实例来调用这样的方法。

protocol PostDelegate 
    func selectedPost(post: Posts)

现在在TableViewCell 中创建它的实例,并在didSelectItemAtIndexPath 中调用这个委托方法。

class TableViewCell: UITableViewCell, UICollectionViewDataSource, UICollectionViewDelegate 
     var posts1: [Posts] = [Posts]()
     var posts2: [Posts] = [Posts]()
     var categories: [Category] = [Category]()
     var selectedPost1: Posts?  
     var postDelegate: PostDelegate?

     func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) 
         postDelegate?. selectedPost(self.posts1[indexPath.row])
     

现在在HomePageTableViewController 中实现这个PostDelegate 协议

class HomePageTableViewController: UITableViewController,UICollectionViewDelegate  


     //Your code 

     func selectedPost(post: Posts) 
         //You will get your post object here, do what you want now
     

注意:cellForRowAtIndexPath 内部不要忘记像这样用HomePageTableViewController 设置postDelgate 的委托

tableViewCell.postDelegate = self

编辑:

func selectedPost(post: Posts) 
    //You will get your post object here, do what you want now
    self.performSegueWithIdentifier("goToDetail", sender: post)


override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) 
    let post = sender as! Posts
    let postDetailPage = segue.destinationViewController as? DetailViewController
    postDetailPage.passPost = post

【讨论】:

对不起,我是 Swift 新手,对创建新协议不是很熟悉。那么你的意思是我需要在我的 TableViewCell 中实现“protocol PostDelegate”吗?之后,我把这个协议放在我的 HomePageTableViewController 中?我已经从 HomePageTableViewController 中删除了“didSelectedItemAtIndexPath”,我还需要这个 HomePageTableViewController 中的“func prepareForSegue”吗? TableViewCell 之外声明协议不在内部,在TableViewCell 内部创建该协议的实例,就像我的回答一样。 你可以在TableViewCell的类之上声明protocol 我已经按照你说的实现了协议。现在在 HomePageTableView 中,我该怎么办?我需要prepareForSegue吗?在func selectedPost(post: Posts) 里面,我应该放什么?谢谢 在情节提要中,如果您已将 segue 与 tablecell 连接,则将其删除并在两个 viewController 之间创建一个,而不是在 Tabelcell 和 viewController 之间创建一个。在 selectedPost 方法中调用 performSegue 之后。【参考方案2】:

所以,你还没有实现

func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int 
...

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

第二个实现中的方法。 另外,尝试在集合视图单元格上放置一个不可见的按钮,并将标签分配为该集合视图单元格的索引路径,如下所示:

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

....
myButton.tag = indexpath.item

在此之后,您可以实现从 collectionviewcell 类到 homepagetableviewcontroller 类的委托回调,或者直接通过代码推送详细视图控制器。

就细节视图控制器中的图像设置而言。您可以在 viewdidLoad() 或 viewDidAppear() 中执行此操作。没关系。

【讨论】:

所以你的意思是我必须在 HomeTableViewController 中实现“numberOfItemInSection”和“cellForItemAtIndexPath”?为什么我需要这样做?我需要返回多少个号码?对于单元格,我该如何实现它?抱歉,我是 Swift 新手。 这与 swift 无关,但一般来说,每个“numberOfItemInSection”都会调用一个“cellForItemAtIndexPath”。因此,如果部分中的项目数为 0(或未提及)。细胞没有形成。因此,“didSelectRowAtIndexPath”不会有任何效果。 但是在我的 HomeTableViewController 中,我有 numberOfRowAtIndexPath 和 cellForRowAtIndexPath。但是,如果我使用 didSelectedRowAtIndexPath,它就无法正常工作。这是为什么?谢谢

以上是关于Swift:如何在 UITableViewController(包含 UICollectionView)中使用“didSelectItemAtIndexPath”?的主要内容,如果未能解决你的问题,请参考以下文章

无法让 UITableViewController 动态填充

我有一个显示 UIActionSheet 的 UITableViewController,如何使操作表选项显示模式视图?

无法在 dealloc 中释放 NSFetchedResultsController

子容器视图中的 UILabel 未更新

将 NSFetchedResultsController 从 UITableViewController 迁移到 UIViewController

如何在 Swift 中从 NSData 显示 PDF - 如何将 PDF 保存到文档文件夹 Swift - 如何在 Swift 中通过 WebView 从保存的 NSData 显示 PDF