Swift: tvOS IBAction для UIControl в ячейке Collection View никогда не вызывается - PullRequest
1 голос
/ 06 июля 2019

Я знаю, что об этом спрашивали много раз, но я все еще учусь, я попробовал все возможные решения здесь, в С.О. и мне не повезло ни разу. Так вот в чем проблема:

  • Я использую Xcode 11 beta 3 (надеюсь, это НЕ проблема!)
  • У меня есть простое представление коллекции в контроллере представления
  • Внутри ячейки я поместил tvOS ' TVPosterView - который наследует от UIControl и сам тестирует его, он действует как кнопка (вызывается IBAction).
  • В представлении коллекции есть анимация, когда я нажимаю на плакат
  • изображение постера имеет изображение по умолчанию, и я просто изменяю заголовок
  • Я перетащил IBAction из представления постера в класс ячеек в IB
  • Помимо IBAction, представление коллекции показывает и прокручивает просто отлично, изменяя названия постеров
  • Если я делегирую представление коллекции контроллеру представления, collectionView (_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) действительно вызывается.

Вот код:

Просмотр контроллера

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

Есть идеи о том, что мне не хватает? Я просто был бы рад напечатать фиктивную строку после нажатия на плакат.

Я также пробовал решения с селекторами и делегатами, ни один не работал. Итак, давайте сконцентрируемся на этом конкретном решении с замыканиями . Спасибо!

1 Ответ

1 голос
/ 06 июля 2019

Я наконец нашел это.Как обычно, это связано с фокусом на 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)")
    }
}

Я протестировал его в коде этого вопроса и добавил также в свой проект, который наконец-то работает!

...