Swift:永远不会调用集合视图单元中 UIControl 的 tvOS IBAction [英] Swift: tvOS IBAction for UIControl in Collection View cell never gets called

查看:25
本文介绍了Swift:永远不会调用集合视图单元中 UIControl 的 tvOS IBAction的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我知道这已经被问过很多次了,但我仍在学习,我在 S.O. 尝试了所有可能的解决方案.而我一次都没有走运.这就是问题所在:

I know this has been asked many times, but I am still learning, I have tried all possible solutions here in S.O. and I haven't had luck a single time. So this is the issue:

  • 我使用的是 Xcode 11 beta 3(希望这不是问题!)
  • 我在视图控制器中有一个简单的集合视图
  • 在单元格内,我放置了一个 tvOS 的 TVPosterView - 它继承自 UIControl并自行测试它确实像一个按钮(IBAction 被调用).
  • 在收藏视图上有我推海报时的动画
  • 海报视图有一个默认图像,我只是更改了标题
  • 我将一个 IBAction 从海报视图拖到 IB 中的单元格类
  • 除了 IBAction,collection 视图显示和滚动都很好,改变了海报的标题
  • 如果我将集合视图委托给视图控制器,collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) 确实会被调用.
  • I am using Xcode 11 beta 3 (hopefully that ISN'T the issue!)
  • I have a simple collection view in a view controller
  • Inside the cell I have put a tvOS' TVPosterView - which inherits from UIControl and testing it by itself it does behave like a button (IBAction gets called).
  • On the collection view there is the animation when I push the poster
  • the poster view has a default image and I just change the title
  • I dragged an IBAction from the poster view to the cell class in IB
  • IBAction apart, the collection view shows and scrolls just fine, changing the titles of the posters
  • If I delegate the collection view to the view controller, collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) does get called.

代码如下:

视图控制器

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)")
    }
}

知道我缺少什么吗?我很乐意在按下海报后设法打印一个虚拟字符串.

Any idea about what I am missing? I would just be happy to manage to print a dummy string after pressing a poster.

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

I have also tried the solutions with selectors and delegates, none worked. So, please let's concentrate on this particular solution with closures. Thanks!

推荐答案

我终于找到了.像往常一样,这是由于 tvOS 的关注.基本上,单元格必须是不可聚焦的,这样单元格内的 UIControl 元素(在我的例子中是 TVPosterView,但它可以是任何 UIControl)将是聚焦的元素.这很诡异,因为从图形上看,它确实看起来好像海报有焦点(可以稍微旋转海报).

I have finally found it. As usual it's due to tvOS focus. Basically the cell has to be not focusable, so that the UIControl element inside the cell (TVPosterView in my case, but it could be any UIControl) will be the focused one. It's tricking because graphically it does appear as if the poster had focus (one can rotate the poster a bit around).

解决办法是添加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)")
    }
}

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

I have tested it in the code of this question and added it also to my project, which finally works!

这篇关于Swift:永远不会调用集合视图单元中 UIControl 的 tvOS IBAction的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆