I have a custom animator (implements the UIViewControllerAnimatedTransitioning
protocol) which I have used for modal segues without issue.
Recently I tried reusing the same animator for a navigation controller (push/ present) segue but immediately ran into some odd behavior.
In particular, I snapshot a subview that I animate on-screen like so:
UIView *fromTitleLabel = [[fromViewController.view viewWithTag:100] snapshotViewAfterScreenUpdates:YES];
... position fromTitleLabel similar to viewWithTag:100 ...
[containerView addSubview:fromTitleLabel];
[fromViewController.view viewWithTag:100].alpha = 0.0;
As you can see I snapshot a label to animate and proceed to hide the original one. This works fine with the modal presentation style, but when using a navigation controller the label is hidden in the snapshot, even though it was taken before changing its opacity.
Changing snapshotViewAfterScreenUpdates
to NO
fixes this, but unfortunately won't work since I also do the same with the destination view which has not yet been added to the view hierarchy.
Wrapping the view.alpha = 0.0
line in a dispatch_async()
block also fixes this, like so:
dispatch_async(dispatch_get_main_queue(), ^{
[fromViewController.view viewWithTag:100].alpha = 0.0;
}
Probably because this allows the screen to update and the snapshot to be taken before changing its alpha.
My question is, how come this "workaround" is not necessary when working with a modal presentation style but is necessary when using a navigation controller's present/ push style? How come changes after calling snapshotAfterUpdates:YES
are included in the snapshot when the documentation clearly states recent changes will be incorporated, not future?