-
Notifications
You must be signed in to change notification settings - Fork 6k
Fix issue viewdidload call while init FlutterViewController #16672
Conversation
chinmaygarde
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The existing behavior is to launch the engine only when UIKit attempts to load the Flutter view. With this patch, the engine will be loaded eagerly even when there is no need to display the same. If the application wants to launch the engine irrespective of the whether its view is being displayed, it can use the engine reference directly to launch the Flutter isolate.
dnfield
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This will break existing usages. If you need this behavior we should probably just create a new initializer.
We should also have a test for it.
chinmaygarde
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I apologize. I was incorrect with my previous comment.
With this patch, the engine will be loaded eagerly even when there is no need to display the same.
This is exactly what you are avoiding with this patch.
The patch looks good but please add a test.
|
But now the viewcontroller won't get attached to the engine right? |
Yeah. You're right. We need to figure out why setting the view controller is implicitly loading the view. This seems like an issue where some other method missed the |
Yeah. But I think that current initializer doesn't follow iOS app lifecycle. We should correct it. |
Viewcontroller will attached to the engine in viewWillAppear - (void)viewWillAppear:(BOOL)animated {
TRACE_EVENT0("flutter", "viewWillAppear");
if (_engineNeedsLaunch) {
[_engine.get() launchEngine:nil libraryURI:nil];
[_engine.get() setViewController:self];
_engineNeedsLaunch = NO;
}
// Send platform settings to Flutter, e.g., platform brightness.
[self onUserSettingsChanged:nil];
// Only recreate surface on subsequent appearances when viewport metrics are known.
// First time surface creation is done on viewDidLayoutSubviews.
if (_viewportMetrics.physical_width) {
[self surfaceUpdated:YES];
}
[[_engine.get() lifecycleChannel] sendMessage:@"AppLifecycleState.inactive"];
[super viewWillAppear:animated];
}Does it make something broken? |
|
Took a little more time to read through some code here. I'm concerned that this change would lead to calling I believe our problem is that when you set the owner view controller, we access its view, which will cause it to load,here:
We should somehow instead only create the surface when the view is actually available, instead of forcing it to load there. That will avoid making unnecessary re-entrant calls to |
| _ongoingTouches = [[NSMutableSet alloc] init]; | ||
|
|
||
| [self performCommonViewControllerInitialization]; | ||
| [engine setViewController:self]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So this line here is what's causing the view to load.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes. That right.
|
A simpler way to handle this for now (without fixing the underlying problem of setting the VC causing it to load the view) would be to avoid setting the VC in the intializer, but conditionally setting it in That seems a little hacky though, and likely to break something in a difficult to understand way. A better resolution here should be to just have the platform view more lazily instantiate the surface it wants, only after some other action has caused the view to load (unless |
b2c7cda to
8e669bf
Compare
|
@dnfield, @chinmaygarde |
ace18f3 to
46def80
Compare
| if (!_isAttchedView) { | ||
| [_engine.get() attachView]; | ||
| _isAttchedView = YES; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we really need this guard? It seems like if we actually loaded a new instance of the view, we'd want to let the engine know about it to update the surface/a11y bridge.
But we would not want to let it know if the view was actually the same view.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that we this guard.
Make sure that we don't create another instance of ios_surface_ in platform_view_ios.mm
I think that this is the same with old logic.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's fine. If this is a bug it's existing and we can address it separately
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should probably FML_DCHECK that owner controller is not nil here though
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added FML_DCHECK.
Thanks
|
also /cc @gaaclarke (GitHub is slow right now and failing to let me add you as a reviewer). |
46def80 to
17dd9d0
Compare
| _engineNeedsLaunch = NO; | ||
| } | ||
|
|
||
| if (!_isAttchedView) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wouldn't this be more appropriate in loadView? Wouldn't that timing more match how it was previously and you wouldn't have to keep an extra bool _isViewAttached?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will loadView ever get called more than once in the lifecycle of a UIViewController?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Talked offline - the answer should be no
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It should only be called once. We should actually use viewDidLoad since it's a bit safer.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So need also call setViewController in viewDidLoad. Is that right?
shell/platform/darwin/ios/framework/Source/FlutterViewController.mm
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
|
Hi @dnfield , @gaaclarke |
|
Hi have anything issues should be fixed with this patch? |
* 7c612de Roll fuchsia/sdk/core/linux-amd64 from cXgMr... to cTw2C... (flutter/engine#16970) * 6cfa7fc fix shadows and mask filter blurs (flutter/engine#16963) * bfebadf Roll src/third_party/skia 012f8497802e..93a2a6b8badb (4 commits) (flutter/engine#16974) * 47963a5 Roll src/third_party/skia 93a2a6b8badb..74055566bd14 (2 commits) (flutter/engine#16981) * 98f9941 [fuchsia] fix broken flows when under high load (flutter/engine#16834) * fe051e0 Fix issue viewdidload call while init FlutterViewController (flutter/engine#16672) * 0ad54c2 [web] Fixes IE11 crash due to missing canvas ellipse support and font polyfill failure (flutter/engine#16965) * f6435de Roll fuchsia/sdk/core/mac-amd64 from J6ct_... to 95geB... (flutter/engine#16982) * 43971ca Roll src/third_party/skia 74055566bd14..54de2fa48d85 (3 commits) (flutter/engine#16983) * 45e61a6 Roll fuchsia/sdk/core/linux-amd64 from cTw2C... to K1wwe... (flutter/engine#16984) * 1ab5c36 Roll src/third_party/skia 54de2fa48d85..beaaf4700f50 (3 commits) (flutter/engine#16987) * e2c0454 remove 10s timeouts from tests (flutter/engine#16988) * dfc9c12 Roll src/third_party/skia beaaf4700f50..6e58290ba639 (9 commits) (flutter/engine#16990) * eddda80 fushia licenses fix (flutter/engine#16992) * c15f239 documented fluttertexture.h (flutter/engine#16950) * e1ba7a1 Roll src/third_party/skia 6e58290ba639..24a8e9e170f7 (5 commits) (flutter/engine#16996) * fc5963d [web] Engine integration test (flutter/engine#16930) * d323bac doxygen tooling updates and doxygen for FlutterCodecs.h (flutter/engine#16947) * 03ddc1d Started deleting .DS_Store files so licenses can run on mac os x. (flutter/engine#16998) * 30a8292 Roll src/third_party/skia 24a8e9e170f7..cf573d844da6 (4 commits) (flutter/engine#17004) * d031963 Roll fuchsia/sdk/core/mac-amd64 from 95geB... to hW33F... (flutter/engine#17006) * 41b371d Roll fuchsia/sdk/core/linux-amd64 from K1wwe... to FGMpI... (flutter/engine#17007) * 619acd5 Revert "fix shadows and mask filter blurs (#16963)" (flutter/engine#17008)
…16672) Co-authored-by: Aaron Clarke <[email protected]>
|
|
||
| #pragma mark - UIViewController lifecycle notifications | ||
|
|
||
| - (void)viewWillAppear:(BOOL)animated { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I get that we moved a bunch of stuff out of PlatformViewIOS::SetOwnerViewController which is definitely the right thing to do. But I'm not sure I understood why the change from viewWillAppear to viewDidLoad. Strictly speaking, viewDidLoad doesn't signal intent. It'll be called even if you just do flutterViewController.view without ever trying to present the FlutterViewController and we'll end up with an IOSSurface and an AccessibilityBridge.
Is it just a convenient way of avoiding having to keep track of whether viewWillAppear was already called once per instance?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
viewDidLoad means we have a valid view we can use. It's up to the developer to make sure they avoid loading the view earlier than they should, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
probably. The side effects is not very obvious however. Might as well take away another foot gun.
Fix issue reported from ticket
flutter/flutter#50949