-
Notifications
You must be signed in to change notification settings - Fork 29.7k
Description
Background
PlatformViews are created asynchronizely through method channel via a onCreate message.
OnCreate essentially constructs a UIView and put it in to the root_view_ map with an id. If the same id is "created" again, the root_view_[$id] is replaced with a newly constructed UIView.
Skip forward to how the root_views are ordered and added to the view tree, the logics are in BringLayersIntoView. We rely on the fact that [UIView addSubview] reorders the view to the top most if the subview is already in the view tree. See: https://github.com/flutter/engine/blob/main/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm#L786-L796. So it doesn't matter if the view is in the view tree, [UIView addSubvIew] takes care adding the view and putting the views at the correct order.
Bug
This causes a potential race condition. Consider the below situation:
root_view_[0] is viewA. And viewA is currently in the view tree, or in another word, a subview of flutter view.
OnCreate is called with id 0, viewB is created, root_view_[0] is changed from viewA to viewB.
During the same frame, BringLayersIntoView is going to get the view from root_view_[0], which is now viewB. Because the view representing id 0 was viewA, viewB is not in the view tree, [UIView addSubview] will add viewB to the view tree. And now we have both viewA and viewB representing id 0 in the view tree. The correct behavior is to only have viewB in this situation.