So I have a view controller that has the following methods:
var viewToFocus: UIView? = nil {
didSet {
if viewToFocus != nil {
self.setNeedsFocusUpdate()
self.updateFocusIfNeeded()
}
}
}
override weak var preferredFocusedView: UIView? {
if viewToFocus != nil {
let theView = viewToFocus
viewToFocus = nil
return theView
} else {
return super.preferredFocusedView;
}
}
So essentially I can force a focus update to the view I want by setting viewToFocus to a value, which works great in most cases. However, when removing a subview this doesn't seem to work properly and preferredFocusedView is never called.
In terms of my subview, it's an overlay that covers the screen (don't ask why I didn't use a modal, there were reasons for that) and has the parent view controller as a delegate. The parent view controller has the following methods:
// Delegate of 'OverlayView'. Called BEFORE it is added as a subview
func beforeOpeningOverlay() {
focusedViewBeforeOverlay = UIScreen.mainScreen().focusedView
}
// Delegate of 'OverlayView'. Called after its close action is triggered.
func closedOverlay(overlay: OverlayView) {
if focusedViewBeforeOverlay != nil {
viewToFocus = focusedViewBeforeOverlay
focusedViewBeforeOverlay = nil
}
overlay.delegate = nil
overlay.removeFromSuperview()
}
For some reason when closedOverlay is called, and focusedViewBeforeOverlay has a valid non-nil view, it is never the next view focused on after the overlay is removed from the superview. Like I said preferredFocusedView is never called, and focus instead focuses on whatever the focus engine decides should be the next focus.
Anyone know why that might be the case? Does removing a subview not allow you to trigger a focus update?
So the order, or at least expected order, should be:
- Something triggers
OverlayViewto be instantiated beforeOpeningOverlay()is called, and the currently focused view is set tofocusedViewBeforeOverlay. The overlay is then opened and captures focus- Something triggers the overlay view to close, calling
closedOverlay() viewToFocus = focusedViewBeforeOverlayline is called- A focus update should be called for the parent viewcontroller, calling its
preferredFocusedView preferredFocusedViewshould returnviewToFocuswhich was set tofocusedViewBeforeOverlayand revert focus back to the view that was focused before the overlay opens
The issue seems to be that step 5 and onwards aren't called
As Roman commented,
referredFocusedViewwas deprecated in tvOS 10. Now you have to define yourpreferredFocusEnvironments.That in your case would be something like:
You also need to call
self.setNeedsFocusUpdate()for updating the focus.