From cfe8675ff58a59dcf96d4e3ca89c8bfa3e7d2a07 Mon Sep 17 00:00:00 2001 From: Chris Yang Date: Mon, 1 Apr 2019 17:06:32 -0700 Subject: [PATCH] Delay platform view removal to submitFrame. (#8380) Remove platform views inside OnDispose might cause issue if it happens before SubmitFrame and the active_composition_order has not been updated. We will be left at a situation where the active_composition_order still contains the old view, but the view is actually removed from the UIView hierarchy. We now cache the views need to be removed in OnDispose and actually remove them in SubmitFrame. At the same time, we remove stop detaching the subviews if they were disposed. As a side effect, this update will also fix flutter/flutter#30220 --- .../framework/Source/FlutterPlatformViews.mm | 28 +++++++++++++++---- .../Source/FlutterPlatformViews_Internal.h | 6 ++++ 2 files changed, 28 insertions(+), 6 deletions(-) diff --git a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm index d3c42ed446..f2f0550b8c 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm @@ -100,12 +100,8 @@ void FlutterPlatformViewsController::OnDispose(FlutterMethodCall* call, FlutterR details:[NSString stringWithFormat:@"view id: '%lld'", viewId]]); return; } - - UIView* touch_interceptor = touch_interceptors_[viewId].get(); - [touch_interceptor removeFromSuperview]; - views_.erase(viewId); - touch_interceptors_.erase(viewId); - overlays_.erase(viewId); + // We wait for next submitFrame to dispose views. + views_to_dispose_.insert(viewId); result(nil); } @@ -213,6 +209,8 @@ void FlutterPlatformViewsController::Reset() { bool FlutterPlatformViewsController::SubmitFrame(bool gl_rendering, GrContext* gr_context, std::shared_ptr gl_context) { + DisposeViews(); + bool did_submit = true; for (size_t i = 0; i < composition_order_.size(); i++) { int64_t view_id = composition_order_[i]; @@ -265,12 +263,30 @@ void FlutterPlatformViewsController::DetachUnusedLayers() { for (int64_t view_id : active_composition_order_) { if (composition_order_set.find(view_id) == composition_order_set.end()) { + if (touch_interceptors_.find(view_id) == touch_interceptors_.end()) { + continue; + } [touch_interceptors_[view_id].get() removeFromSuperview]; [overlays_[view_id]->overlay_view.get() removeFromSuperview]; } } } +void FlutterPlatformViewsController::DisposeViews() { + if (views_to_dispose_.empty()) { + return; + } + + for (int64_t viewId : views_to_dispose_) { + UIView* touch_interceptor = touch_interceptors_[viewId].get(); + [touch_interceptor removeFromSuperview]; + views_.erase(viewId); + touch_interceptors_.erase(viewId); + overlays_.erase(viewId); + } + views_to_dispose_.clear(); +} + void FlutterPlatformViewsController::EnsureOverlayInitialized(int64_t overlay_id) { if (overlays_.count(overlay_id) != 0) { return; diff --git a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h index a0ebbac98b..0f2cfe3d57 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h +++ b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h @@ -91,6 +91,10 @@ class FlutterPlatformViewsController { GrContext* overlays_gr_context_; SkISize frame_size_; + // Method channel `OnDispose` calls adds the views to be disposed to this set to be disposed on + // the next frame. + std::unordered_set views_to_dispose_; + // A vector of embedded view IDs according to their composition order. // The last ID in this vector belond to the that is composited on top of all others. std::vector composition_order_; @@ -106,6 +110,8 @@ class FlutterPlatformViewsController { void OnRejectGesture(FlutterMethodCall* call, FlutterResult& result); void DetachUnusedLayers(); + // Dispose the views in `views_to_dispose_`. + void DisposeViews(); void EnsureOverlayInitialized(int64_t overlay_id); void EnsureGLOverlayInitialized(int64_t overlay_id, std::shared_ptr gl_context, -- GitLab