首页 > 解决方案 > Swift:集合视图单元中 UIControl 的 tvOS IBAction 永远不会被调用

问题描述

我知道这已经被问过很多次了,但我仍在学习,我已经在 SO 中尝试了所有可能的解决方案,但我一次都没有运气。所以这是问题:

这是代码:

视图控制器

import UIKit
import TVUIKit

class SecondViewController: UIViewController {

    @IBOutlet weak var myView: UIView!
    @IBOutlet weak var myCollection: MyCollection!

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
    }
}

extension SecondViewController: UICollectionViewDataSource {

    func numberOfSections(in collectionView: UICollectionView) -> Int {
        return 1
    }

    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return 10
    }

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

        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "MyCell", for: indexPath) as! MyCell

        cell.myPoster.title! = "Header " + String(indexPath.row + 1)

        cell.myPoster.tag = indexPath.row + 1
        cell.posterTapAction = { cell in
            print("Header is: \(cell.myPoster.title!)")
        }

        return cell
    }
}

extension SecondViewController: UICollectionViewDelegate {

    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
// This one works - but that's not what I am looking for
        print("From didSelectItemAt indexPath: \(indexPath.item + 1)")
    }
}

集合视图

import UIKit

class MyCollection: UICollectionView {

    override func awakeFromNib() {
        super.awakeFromNib()
    }

    override func layoutSubviews() {
        super.layoutSubviews()
    }
}

细胞

import UIKit
import TVUIKit

class MyCell: UICollectionViewCell {

    var posterTapAction: ((MyCell) -> Void)?

    @IBOutlet weak var myPoster: TVPosterView!
    @IBAction func myAction(_ sender: TVPosterView) {
        posterTapAction?(self)
        print("Poster pressed \(sender.tag)")
    }
}

关于我缺少什么的任何想法?我很乐意在按下海报后设法打印一个虚拟字符串。

我也尝试过使用选择器和委托的解决方案,但都没有奏效。所以,请让我们专注于这个带有闭包的特殊解决方案。谢谢!

标签: swiftuicollectionviewuibuttonuicollectionviewcelltvos

解决方案


我终于找到了。像往常一样,这是由于 tvOS 的焦点。基本上,单元格必须不可聚焦,以便单元格内的 UIControl 元素(在我的情况下为 TVPosterView,但它可以是任何 UIControl)将成为焦点。这是骗人的,因为从图形上看,它确实看起来好像海报有焦点(可以将海报旋转一点)。

解决方案是将collectionView(_:canFocusItemAt:)添加到UICollectionViewDelegate

extension SecondViewController: UICollectionViewDelegate {

    func collectionView(_ collectionView: UICollectionView,
                             canFocusItemAt indexPath: IndexPath) -> Bool {
        return false
    }

    func collectionView(_ collectionView: UICollectionView, 
                             didSelectItemAt indexPath: IndexPath) {
        // Now, thanks to the function above, this is disabled
        print("From didSelectItemAt indexPath: \(indexPath.item + 1)")
    }
}

我已经在这个问题的代码中对其进行了测试,并将它也添加到了我的项目中,它终于可以工作了!


推荐阅读