Skip to content

Commit bec0dac

Browse files
authored
Fix not being able to hide iOS status bar via setEnabledSystemUIMode (flutter#48271)
Fix flutter#138604 and flutter#138671 Related PR flutter/engine#45351 [C++, Objective-C, Java style guides]: https://github.com/flutter/engine/blob/main/CONTRIBUTING.md#style
1 parent 5733891 commit bec0dac

2 files changed

Lines changed: 91 additions & 2 deletions

File tree

shell/platform/darwin/ios/framework/Source/FlutterPlatformPlugin.mm

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,15 +43,15 @@
4343
using namespace flutter;
4444

4545
static void SetStatusBarHiddenForSharedApplication(BOOL hidden) {
46-
#if APPLICATION_EXTENSION_API_ONLY
46+
#if not APPLICATION_EXTENSION_API_ONLY
4747
[UIApplication sharedApplication].statusBarHidden = hidden;
4848
#else
4949
FML_LOG(WARNING) << "Application based status bar styling is not available in app extension.";
5050
#endif
5151
}
5252

5353
static void SetStatusBarStyleForSharedApplication(UIStatusBarStyle style) {
54-
#if APPLICATION_EXTENSION_API_ONLY
54+
#if not APPLICATION_EXTENSION_API_ONLY
5555
// Note: -[UIApplication setStatusBarStyle] is deprecated in iOS9
5656
// in favor of delegating to the view controller.
5757
[[UIApplication sharedApplication] setStatusBarStyle:style];

shell/platform/darwin/ios/framework/Source/FlutterPlatformPluginTest.mm

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -408,4 +408,93 @@ - (void)testViewControllerBasedStatusBarHiddenUpdate {
408408
[bundleMock stopMocking];
409409
}
410410

411+
- (void)testStatusBarHiddenUpdate {
412+
id bundleMock = OCMPartialMock([NSBundle mainBundle]);
413+
OCMStub([bundleMock objectForInfoDictionaryKey:@"UIViewControllerBasedStatusBarAppearance"])
414+
.andReturn(@NO);
415+
id mockApplication = OCMClassMock([UIApplication class]);
416+
OCMStub([mockApplication sharedApplication]).andReturn(mockApplication);
417+
418+
// Enabling system UI overlays to update status bar.
419+
FlutterEngine* engine = [[FlutterEngine alloc] initWithName:@"test" project:nil];
420+
[engine runWithEntrypoint:nil];
421+
FlutterViewController* flutterViewController =
422+
[[FlutterViewController alloc] initWithEngine:engine nibName:nil bundle:nil];
423+
std::unique_ptr<fml::WeakNSObjectFactory<FlutterEngine>> _weakFactory =
424+
std::make_unique<fml::WeakNSObjectFactory<FlutterEngine>>(engine);
425+
426+
// Update to hidden.
427+
FlutterPlatformPlugin* plugin = [engine platformPlugin];
428+
429+
XCTestExpectation* enableSystemUIOverlaysCalled =
430+
[self expectationWithDescription:@"setEnabledSystemUIOverlays"];
431+
FlutterResult resultSet = ^(id result) {
432+
[enableSystemUIOverlaysCalled fulfill];
433+
};
434+
FlutterMethodCall* methodCallSet =
435+
[FlutterMethodCall methodCallWithMethodName:@"SystemChrome.setEnabledSystemUIOverlays"
436+
arguments:@[ @"SystemUiOverlay.bottom" ]];
437+
[plugin handleMethodCall:methodCallSet result:resultSet];
438+
[self waitForExpectationsWithTimeout:1 handler:nil];
439+
#if not APPLICATION_EXTENSION_API_ONLY
440+
OCMVerify([mockApplication setStatusBarHidden:YES]);
441+
#endif
442+
443+
// Update to shown.
444+
XCTestExpectation* enableSystemUIOverlaysCalled2 =
445+
[self expectationWithDescription:@"setEnabledSystemUIOverlays"];
446+
FlutterResult resultSet2 = ^(id result) {
447+
[enableSystemUIOverlaysCalled2 fulfill];
448+
};
449+
FlutterMethodCall* methodCallSet2 =
450+
[FlutterMethodCall methodCallWithMethodName:@"SystemChrome.setEnabledSystemUIOverlays"
451+
arguments:@[ @"SystemUiOverlay.top" ]];
452+
[plugin handleMethodCall:methodCallSet2 result:resultSet2];
453+
[self waitForExpectationsWithTimeout:1 handler:nil];
454+
#if not APPLICATION_EXTENSION_API_ONLY
455+
OCMVerify([mockApplication setStatusBarHidden:NO]);
456+
#endif
457+
458+
[flutterViewController deregisterNotifications];
459+
[mockApplication stopMocking];
460+
[bundleMock stopMocking];
461+
}
462+
463+
- (void)testStatusBarStyle {
464+
id bundleMock = OCMPartialMock([NSBundle mainBundle]);
465+
OCMStub([bundleMock objectForInfoDictionaryKey:@"UIViewControllerBasedStatusBarAppearance"])
466+
.andReturn(@NO);
467+
id mockApplication = OCMClassMock([UIApplication class]);
468+
OCMStub([mockApplication sharedApplication]).andReturn(mockApplication);
469+
470+
FlutterEngine* engine = [[FlutterEngine alloc] initWithName:@"test" project:nil];
471+
[engine runWithEntrypoint:nil];
472+
FlutterViewController* flutterViewController =
473+
[[FlutterViewController alloc] initWithEngine:engine nibName:nil bundle:nil];
474+
std::unique_ptr<fml::WeakNSObjectFactory<FlutterEngine>> _weakFactory =
475+
std::make_unique<fml::WeakNSObjectFactory<FlutterEngine>>(engine);
476+
XCTAssertFalse(flutterViewController.prefersStatusBarHidden);
477+
478+
FlutterPlatformPlugin* plugin = [engine platformPlugin];
479+
480+
XCTestExpectation* enableSystemUIModeCalled =
481+
[self expectationWithDescription:@"setSystemUIOverlayStyle"];
482+
FlutterResult resultSet = ^(id result) {
483+
[enableSystemUIModeCalled fulfill];
484+
};
485+
FlutterMethodCall* methodCallSet =
486+
[FlutterMethodCall methodCallWithMethodName:@"SystemChrome.setSystemUIOverlayStyle"
487+
arguments:@{@"statusBarBrightness" : @"Brightness.dark"}];
488+
[plugin handleMethodCall:methodCallSet result:resultSet];
489+
[self waitForExpectationsWithTimeout:1 handler:nil];
490+
491+
#if not APPLICATION_EXTENSION_API_ONLY
492+
OCMVerify([mockApplication setStatusBarStyle:UIStatusBarStyleLightContent]);
493+
#endif
494+
495+
[flutterViewController deregisterNotifications];
496+
[mockApplication stopMocking];
497+
[bundleMock stopMocking];
498+
}
499+
411500
@end

0 commit comments

Comments
 (0)