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:
Here is the code:
View Controller
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)")
}
}
Collection View
import UIKit
class MyCollection: UICollectionView {
override func awakeFromNib() {
super.awakeFromNib()
}
override func layoutSubviews() {
super.layoutSubviews()
}
}
Cell
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!
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).
The solution is to add collectionView(_:canFocusItemAt:) to the 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!