已有项目接入Flutter第二次不展示的问题
已有项目接入Flutter第二次不展示的问题
问题
在已有iOS项目里接入
flutter
模块后,第一次present
或push
一个FlutterViewController
后,通过手势或调用方法关闭flutter页面后,再次present
或push
时展示不了flutter页面了
原因:
flutter
页面关闭后,flutterEngine.viewController
还是持有FlutterViewController
,导致FlutterViewController
不销毁,下次调用present
或push
时就展示不了
解决方案
自定义一个FlutterViewController
并在viewDidDisappear(:)
里判断如果是销毁则将flutterEngine.viewController
设置为nil
,具体代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
class MyFlutterViewController: FlutterViewController {
deinit {
print("deinit--\(self)")
}
override func viewDidLoad() {
print("viewDidLoad--\(self)")
self.view.backgroundColor = .white
super.viewDidLoad()
}
override func viewDidDisappear(_ animated: Bool) {
print("viewDidDisappear--isBeingDismissed:\(self.isBeingDismissed)--isMovingFromParent:\(self.isMovingFromParent)--\(self)")
super.viewDidDisappear(animated)
// 判断是否是被销毁
if self.isBeingDismissed || self.isMovingFromParent {
// isBeingDismissed: present展示的,拖拽到底部、或调用dismiss关闭时,值为true
// isMovingFromParent:push展示的,侧滑、或者调用pop返回关闭时,值为true
// 执行销毁或清理操作
if let engine = (UIApplication.shared.delegate as? AppDelegate)?.engine,
engine.viewController == self {
engine.viewController = nil
engine.destroyContext()
(UIApplication.shared.delegate as? AppDelegate)?.engine = nil
}
print("FlutterViewController 被销毁")
} else {
// 只是暂时隐藏,不执行销毁操作
print("FlutterViewController 被隐藏")
}
}
override func dismiss(animated flag: Bool, completion: (() -> Void)? = nil) {
print("dismiss(animated:completion:)--\(self)")
super.dismiss(animated: flag, completion: completion)
}
}
完整代码: AppDelegate.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
import UIKit
import Flutter
import FlutterPluginRegistrant
@main
class AppDelegate: UIResponder, UIApplicationDelegate {
private var flutterEngine : FlutterEngine?
var engine: FlutterEngine? {
get {
if let engine = flutterEngine {
return engine
}
let engine = FlutterEngine(name: "xxxx", project: nil)
self.flutterEngine = engine
self.flutterEngine?.run(withEntrypoint: nil)
GeneratedPluginRegistrant.register(with: engine)
return engine
} set {
if newValue == nil {
// 清空
flutterEngine = nil
} else {
flutterEngine = newValue
}
}
}
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
return true
}
}
完整的MyViewController
+ MyFlutterViewController
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
import UIKit
import Flutter
class MyViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let btn = UIButton(type: .custom)
btn.frame = CGRect(x: 50, y: 100, width: 200, height: 50)
btn.backgroundColor = .blue
btn.setTitle("present 进入flutter页面", for: .normal)
btn.addTarget(self, action: #selector(enterFlutterPage(btn:)), for: .touchUpInside)
self.view.addSubview(btn)
let btn2 = UIButton(type: .custom)
btn2.frame = CGRect(x: 50, y: 200, width: 200, height: 50)
btn2.backgroundColor = .blue
btn2.setTitle("push 进入flutter页面", for: .normal)
btn2.tag = 2
btn2.addTarget(self, action: #selector(enterFlutterPage(btn:)), for: .touchUpInside)
self.view.addSubview(btn2)
}
// MARK: App进入flutter页面
@objc func enterFlutterPage(btn: UIButton) {
if let engine = (UIApplication.shared.delegate as? AppDelegate)?.engine {
let flutterViewController = MyFlutterViewController(engine: engine, nibName: nil, bundle: nil)
// 全屏展示
if btn.tag == 2 {
self.navigationController?.pushViewController(flutterViewController, animated: false)
} else {
// flutterViewController.modalPresentationStyle = .fullScreen
self.present(flutterViewController, animated: false, completion: nil)
}
}
}
}
class MyFlutterViewController: FlutterViewController {
deinit {
print("deinit--\(self)")
}
override func viewDidLoad() {
print("viewDidLoad--\(self)")
self.view.backgroundColor = .white
super.viewDidLoad()
}
override func viewDidDisappear(_ animated: Bool) {
print("viewDidDisappear--isBeingDismissed:\(self.isBeingDismissed)--isMovingFromParent:\(self.isMovingFromParent)--\(self)")
super.viewDidDisappear(animated)
// 判断是否是被销毁
if self.isBeingDismissed || self.isMovingFromParent {
// isBeingDismissed: present展示的,拖拽到底部、或调用dismiss关闭时,值为true
// isMovingFromParent:push展示的,侧滑、或者调用pop返回关闭时,值为true
// 执行销毁或清理操作
if let engine = (UIApplication.shared.delegate as? AppDelegate)?.engine,
engine.viewController == self {
engine.viewController = nil
engine.destroyContext()
(UIApplication.shared.delegate as? AppDelegate)?.engine = nil
}
print("FlutterViewController 被销毁")
} else {
// 只是暂时隐藏,不执行销毁操作
print("FlutterViewController 被隐藏")
}
}
override func dismiss(animated flag: Bool, completion: (() -> Void)? = nil) {
print("dismiss(animated:completion:)--\(self)")
super.dismiss(animated: flag, completion: completion)
}
}
This post is licensed under CC BY 4.0 by the author.