Home > front end >  AppleTV app crashes because of a UITableViewCell not providing a parentFocusEnvironment
AppleTV app crashes because of a UITableViewCell not providing a parentFocusEnvironment

Time:10-14

Since Xcode 14 (AppleTV SDK 16.0) and tvOS 16.0, my AppleTV app crashes when I try to call reloadData() on a UITableView after the user selects a cell (the goal is to update the table model and view). The crash states that a UITableViewCell does not have a parentFocusEnvironment:

*** Assertion failure in -[_UIFocusItemInfo _createFocusedRegion], _UIFocusItemInfo.m:187
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Focus item <UITableViewCell: 0x7f92d202fc00> does not provide a parentFocusEnvironment.'

The app creates regular UITableViewCell hence does not override this property so I don't understand why it is missing.

• On tvOS 15.4 (whatever Xcode version 13.4.1 or 14), the app does not crash and the behaviour is as expected. No system warnings or logs.

• On tvOS 16.0 with XCode 13.4.1 (AppleTV SDK 15.0), the app does not crash either but the unfocused view of the selected UITableViewCell stays in the view hierarchy after the reloading. Also a system log warns that the focus item (UITableViewCell) does not define a parentFocusEnvironment and that the app will crash in a future version -> my crash.

[Assert] Focus item <UITableViewCell: 0x7fe4290a7c00> does not provide a parentFocusEnvironment.  This will become an assert in a future version.
[Assert] Failed to create FocusRegion for FocusItem: <UITableViewCell: 0x7ff129856600; frame = (0 800; 880 66); text = 'Show empty sections'; autoresize = W; layer = <CALayer: 0x600003a1f740>> with parentFocusEnvironment: (null)  focusItemContainer: (null)

I've been able to create a sample project where the crash can be reproduced: https://github.com/aureliencolas/NavAndTableView

I've filed a feedback request to Apple a week ago with the sample project but I've got no response so far.

Any advice on how to refresh the tableView in a more appropriate way is welcome.

CodePudding user response:

After requesting a code-level support, an Apple engineer helped me find the fix.

Turns out I was not recycling UITableView cells, but creating new ones each time (which I don't usually do but, in this context, there were no point in recycling cells) and doing so, the cell's parentFocusEnvironment was not always defined.

As it was working fine before tvOS 16 and cells recycling not being mandatory, I still consider it a TVOS 16 regression but the issue is now fixed and it's what matters.

CodePudding user response:

I see the same crash on iPadOS when contents of a focussed table view are cleared. The table view correctly removes the focus and informs the delegate in - (void)tableView:(UITableView *)tableView didUpdateFocusInContext:(UITableViewFocusUpdateContext *)context withAnimationCoordinator:(UIFocusAnimationCoordinator *)coordinator . However, the view crashes after that delegate method is invoked, stating that the old view, which had focus before, does not have a parentFocusEnvironment, since it had been removed from the view hierarchy.

The crash occurred in the next layout phase after the table view updated, since focus updates appear to happen during layout. This table already uses cell recycling, so that could not be the solution as mentioned in other answers.

The fix was to remove the selection from the table view before calling reloadData like so (assuming selectionFollowsFocus is set on the table view):

// Gather data..

if (!hasRowToFocus) {
    // Remove selection
    [self.tableView selectRowAtIndexPath:nil animated:NO scrollPosition:UITableViewScrollPositionNone];
    
    // Update focus while the old focussed view is still visible to avoid the crash
    [self.tableView setNeedsFocusUpdate];
    [self.tableView updateFocusIfNeeded];
}

// Proceed with table view updates..
[tableView reloadData];
...

I'd also consider this a bug, since the SDKs focus validation ignores the fact that an old view might be removed from the view hierarchy and thus lacking a parentFocusEnvironment.

  • Related