Skip to content

Commit da32b26

Browse files
author
caven775
committed
解决iOS字dismiss手势返回时flutterEngine被暂停的问题
1 parent 50bbaf5 commit da32b26

File tree

6 files changed

+95
-11
lines changed

6 files changed

+95
-11
lines changed

example/ios/Runner/AppDelegate.m

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ - (void)dStack:(nonnull DStack *)stack presentWithNode:(nonnull DStackNode *)nod
8484
UINavigationController *navi = [self dStack:stack navigationControllerForNode:node];
8585
if ([node.route isEqualToString:@"NativePage2"]) {
8686
didPushController = [[FourViewController alloc] init];
87-
[navi.topViewController presentViewController:didPushController animated:node.animated completion:nil];
87+
[[self currentController] presentViewController:didPushController animated:node.animated completion:nil];
8888
}
8989
}
9090
//navi = 0x000000016d5720b0

example/ios/Runner/DStackTestCase.m

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#import "SecondViewController.h"
1111
#import "FiveViewController.h"
1212
#import "DStackViewController.h"
13+
#import "DemoFlutterViewController.h"
1314

1415
@implementation DStackTestCase
1516
{
@@ -42,14 +43,14 @@ - (void)initData
4243
@{
4344
@"text": @"打开Flutter page4",
4445
@"clicked": ^(UIViewController *controller) {
45-
[[DStack sharedInstance] pushFlutterPageWithFlutterClass:DFlutterViewController.class
46+
[[DStack sharedInstance] pushFlutterPageWithFlutterClass:DemoFlutterViewController.class
4647
route:@"page4"];
4748
}
4849
},
4950
@{
5051
@"text": @"打开Flutter page1 有参数",
5152
@"clicked": ^(UIViewController *controller) {
52-
[[DStack sharedInstance] pushFlutterPageWithFlutterClass:DFlutterViewController.class
53+
[[DStack sharedInstance] pushFlutterPageWithFlutterClass:DemoFlutterViewController.class
5354
route:@"page1"
5455
params:@{@"fromNative": @"来自原生"}];
5556
}
@@ -66,7 +67,7 @@ - (void)initData
6667
@{
6768
@"text": @"打开Flutter page5",
6869
@"clicked": ^(UIViewController *controller) {
69-
[[DStack sharedInstance] pushFlutterPageWithFlutterClass:DFlutterViewController.class
70+
[[DStack sharedInstance] pushFlutterPageWithFlutterClass:DemoFlutterViewController.class
7071
route:@"page5"];
7172
}
7273
},
@@ -92,7 +93,7 @@ - (void)initData
9293
@{
9394
@"text": @"打开Flutter page6",
9495
@"clicked": ^(UIViewController *controller) {
95-
[[DStack sharedInstance] pushFlutterPageWithFlutterClass:DFlutterViewController.class
96+
[[DStack sharedInstance] pushFlutterPageWithFlutterClass:DemoFlutterViewController.class
9697
route:@"page6"];
9798
}
9899
},
@@ -137,13 +138,17 @@ - (void)initData
137138
@{
138139
@"text": @"返回",
139140
@"clicked": ^(UIViewController *controller) {
140-
[controller dismissViewControllerAnimated:YES completion:nil];
141+
if (controller.navigationController.viewControllers.count > 1) {
142+
[controller.navigationController popViewControllerAnimated:YES];
143+
} else {
144+
[controller dismissViewControllerAnimated:YES completion:nil];
145+
}
141146
}
142147
},
143148
@{
144149
@"text": @"打开Flutter page6",
145150
@"clicked": ^(UIViewController *controller) {
146-
[[DStack sharedInstance] pushFlutterPageWithFlutterClass:DFlutterViewController.class
151+
[[DStack sharedInstance] pushFlutterPageWithFlutterClass:DemoFlutterViewController.class
147152
route:@"page6"];
148153
}
149154
},

example/lib/main.dart

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,18 @@ class _MyAppState extends State<MyApp> with WidgetsBindingObserver {
2424
@override
2525
void initState() {
2626
super.initState();
27+
WidgetsBinding.instance.addObserver(this);
28+
}
29+
30+
@override
31+
void dispose() {
32+
WidgetsBinding.instance.removeObserver(this);
33+
super.dispose();
34+
}
35+
36+
@override
37+
void didChangeAppLifecycleState(AppLifecycleState state) {
38+
print("didChangeAppLifecycleState ==== $state");
2739
}
2840

2941
@override

ios/Classes/Stack/DFlutterViewController.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@ NS_ASSUME_NONNULL_BEGIN
1313
/// 当需要打开一个Flutter页面时,必须是DFlutterViewController或者是它的子类
1414
@interface DFlutterViewController : FlutterViewController
1515

16+
- (void)willUpdateView;
17+
- (void)didUpdateView;
18+
1619
@end
1720

1821
NS_ASSUME_NONNULL_END

ios/Classes/Stack/DFlutterViewController.m

Lines changed: 36 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,10 @@ @implementation DFlutterViewController
1414

1515
- (instancetype)init
1616
{
17-
if(self = [super initWithEngine:[DStack sharedInstance].engine
17+
if (self.dStackFlutterEngine.viewController) {
18+
self.dStackFlutterEngine.viewController = nil;
19+
}
20+
if(self = [super initWithEngine:self.dStackFlutterEngine
1821
nibName:nil
1922
bundle:nil]) {
2023
[self config];
@@ -24,7 +27,10 @@ - (instancetype)init
2427

2528
- (instancetype)initWithCoder:(NSCoder *)coder
2629
{
27-
if(self = [super initWithEngine:[DStack sharedInstance].engine
30+
if (self.dStackFlutterEngine.viewController) {
31+
self.dStackFlutterEngine.viewController = nil;
32+
}
33+
if(self = [super initWithEngine:self.dStackFlutterEngine
2834
nibName:nil
2935
bundle:nil]) {
3036
[self config];
@@ -42,8 +48,9 @@ - (void)viewWillAppear:(BOOL)animated
4248
{
4349
// 必须在页面显示之前判断engine是否存在FlutterViewController
4450
// 否则会因为FlutterViewController不存在而崩溃
45-
if ([DStack sharedInstance].engine.viewController != self) {
46-
[DStack sharedInstance].engine.viewController = self;
51+
if (self.dStackFlutterEngine.viewController != self) {
52+
self.dStackFlutterEngine.viewController = nil;
53+
self.dStackFlutterEngine.viewController = self;
4754
}
4855
[super viewWillAppear:animated];
4956
}
@@ -61,6 +68,26 @@ - (void)viewDidDisappear:(BOOL)animated
6168
[super viewDidDisappear:animated];
6269
}
6370

71+
/// dismiss手势不会触发页面的viewWillAppear
72+
/// viewDidDisappear里面,flutter会让Engine暂停,不会渲染flutter页面
73+
/// 在dismiss的某些情况下,主动调用viewWillAppear,使Engine进入inactive状态
74+
- (void)willUpdateView
75+
{
76+
[self viewWillAppear:YES];
77+
}
78+
79+
/// dismiss手势不会触发页面的viewDidAppear
80+
/// viewDidDisappear里面,flutter会让Engine暂停,不会渲染flutter页面
81+
/// 在dismiss的某些情况下,主动调用viewDidAppear,使Engine进入resumed状态
82+
- (void)didUpdateView
83+
{
84+
[self viewDidAppear:YES];
85+
/// 调用这个是为了重新计算页面的布局
86+
/// 因为在非全屏present页面时,该页面是没有状态栏的
87+
/// 所以在dismiss的时候,需要重新展示状态栏,就需要刷新flutter的页面
88+
[super viewDidLayoutSubviews];
89+
}
90+
6491
- (void)_surfaceUpdated:(BOOL)appeared
6592
{
6693
SEL sel = NSSelectorFromString(@"surfaceUpdated:");
@@ -99,6 +126,11 @@ - (void)changeBottomBarVisible:(NSNotification *)notification
99126
}
100127
}
101128

129+
- (FlutterEngine *)dStackFlutterEngine
130+
{
131+
return [DStack sharedInstance].engine;
132+
}
133+
102134
- (void)dealloc
103135
{
104136
[[NSNotificationCenter defaultCenter] removeObserver:self];

ios/Classes/Stack/DNavigator.m

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
#import "DNavigator.h"
1010
#import "DNodeManager.h"
1111
#import "DActionManager.h"
12+
#import "DStack.h"
13+
#import "DFlutterViewController.h"
1214

1315
typedef void (^_DStackViewControllerWillAppearInjectBlock)(UIViewController *viewController, BOOL animated);
1416

@@ -232,6 +234,26 @@ - (BOOL)presentationControllerShouldDismiss:(UIPresentationController *)presenta
232234

233235
- (void)presentationControllerWillDismiss:(UIPresentationController *)presentationController API_AVAILABLE(ios(13.0))
234236
{
237+
UIViewController *presented = presentationController.presentedViewController;
238+
if ([presented isKindOfClass:UINavigationController.class]) {
239+
presented = [(UINavigationController *)presented topViewController];
240+
}
241+
UIViewController *willAppear = presented.presentingViewController;
242+
if ([willAppear isKindOfClass:UITabBarController.class]) {
243+
willAppear = [(UITabBarController *)willAppear selectedViewController];
244+
if ([willAppear isKindOfClass:UINavigationController.class]) {
245+
willAppear = [(UINavigationController *)willAppear topViewController];
246+
}
247+
} else if ([willAppear isKindOfClass:UINavigationController.class]) {
248+
willAppear = [(UINavigationController *)willAppear topViewController];
249+
}
250+
if ([willAppear isKindOfClass:DFlutterViewController.class]) {
251+
DStack *stack = [DStack sharedInstance];
252+
if (!stack.engine.viewController) {
253+
DFlutterViewController *flutterVC = (DFlutterViewController *)willAppear;
254+
[flutterVC willUpdateView];
255+
}
256+
}
235257
[self checkSelectorToDelegate:@selector(presentationControllerWillDismiss:)
236258
controller:presentationController
237259
forward:^(id<UIAdaptivePresentationControllerDelegate> delegate) {
@@ -247,6 +269,16 @@ - (void)presentationControllerDidDismiss:(UIPresentationController *)presentatio
247269
target = [[(UINavigationController *)presented viewControllers] firstObject];
248270
checkNode(target, DNodeActionTypePopTo);
249271
}
272+
273+
DNodeManager *manager = [DNodeManager sharedInstance];
274+
DNode *didAppearNode = [manager preNode];
275+
if (didAppearNode.pageType == DNodePageTypeFlutter) {
276+
DStack *stack = [DStack sharedInstance];
277+
if (stack.engine.viewController) {
278+
DFlutterViewController *flutterVC = (DFlutterViewController *)stack.engine.viewController;
279+
[flutterVC didUpdateView];
280+
}
281+
}
250282
checkNode(target, DNodeActionTypeGesture);
251283
[self checkSelectorToDelegate:@selector(presentationControllerDidDismiss:)
252284
controller:presentationController

0 commit comments

Comments
 (0)