Search code examples
swiftuicollectionviewuitabbarcontrollertvos

tvOS: How to Handle Focus Change between TabBar and UICollectionView and Prevent Crashing


I created a test tvOS app via Xcode's tvOS "tabbed application" choice. In the first tab view controller at put a UIcollectionView with some simple text cells.

When the app runs, it's possible to move down from the tab bar to the UICollectionView, which accepts focus and one can move among view's items without issue.

However, attempt to move back up to the tab bar from the UICollectionView crashes the app with the following message:

Could not cast value of type 'UITabBarButton' (0x199b92828) to 'tabtest.itemCell' (0x1000153c8).

I presume this means that the focus engine is only "seeing" the the collectionView and that I have to add code to handle the jump back to the UITabBarButton.

I have searched high and low for information on how to handle the focus change and have found nothing specific. Being new to iOS/tvOS development, I am probably missing something obvious.

Can someone please explain how to manage focus between the tab bar and the UICollectionView?

Here is the code I am using to handle focus for the UICollectionView:

// For Focus Engine  
func collectionView(collectionView: UICollectionView, didUpdateFocusInContext context: UICollectionViewFocusUpdateContext, withAnimationCoordinator coordinator: UIFocusAnimationCoordinator) {
}

func collectionView(collectionView: UICollectionView, shouldUpdateFocusInContext context: UICollectionViewFocusUpdateContext) -> Bool {
    if let cell: UICollectionViewCell = context.nextFocusedView as! itemCell{
        _ = self.collectionView.indexPathForCell(cell)
    }
    return true
}

Solution

  • The answer was to realize that the "if let cell . . ." was not needed. Adding the following made it work properly.

    // For Focus Engine

    func collectionView(collectionView: UICollectionView, didUpdateFocusInContext context: UICollectionViewFocusUpdateContext, withAnimationCoordinator coordinator: UIFocusAnimationCoordinator) {
    }
    
    func collectionView(collectionView: UICollectionView, canFocusItemAtIndexPath indexPath: NSIndexPath) -> Bool {
        return true
    }
    
    func collectionView(collectionView: UICollectionView, shouldUpdateFocusInContext context: UICollectionViewFocusUpdateContext) -> Bool {
        return true
    }
    
    func collectionView(collectionView: UICollectionView, shouldSlectItemAtIndexPath context: UICollectionViewFocusUpdateContext) -> Bool {
        return true
    }