美文网首页Flutter
iOS+Flutter--FlutterBoost(二)

iOS+Flutter--FlutterBoost(二)

作者: Red_Wang | 来源:发表于2020-09-08 16:55 被阅读0次

    iOS+Flutter--FlutterBoost(一)

    上一章介绍了iOS项目如何集成FlutterBoost,这一章介绍使用FlutterBoost管理页面。

    一、修改AppDelegate

    import UIKit
    
    // 导入Flutter
    import Flutter
    import flutter_boost
    
    @UIApplicationMain
    class AppDelegate: FlutterAppDelegate { //将UIResponder, UIApplicationDelegate替换为FlutterAppDelegate
    
        // var window: UIWindow?  //去除window声明,因为FlutterAppDelegate中已经声明
    
        override func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
    
            self.window = UIWindow(frame: UIScreen.main.bounds)
            let rootViewController = UINavigationController(rootViewController: FirstViewController())
            self.window?.rootViewController = rootViewController
            self.window?.backgroundColor = .white
            self.window?.makeKeyAndVisible()
    
            let router: FLBPlatform = PlatformRouter()
            FlutterBoostPlugin.sharedInstance().startFlutter(with: router) { (flutterEngine) in
                print("#######  flutterEngine  #########")
            }
    
            return true
        }
    }
    

    二、添加PlatformRouter,代码如下:

    import Foundation
    import flutter_boost
    
    class PlatformRouter: NSObject, FLBPlatform {
        
        func openNative(_ url: String, urlParams: [AnyHashable : Any],
                        exts: [AnyHashable : Any], animated: Bool,
                        completion: @escaping (Bool) -> Void) {
            
            let prefix = "nativebus://"
            guard url.hasPrefix(prefix) else {
                completion(false)
                return
            }
            
            let namespace = Bundle.main.infoDictionary!["CFBundleExecutable"] as! String
            let viewControllerName = String(url.dropFirst(prefix.count))
            guard let cls: AnyClass = NSClassFromString(namespace + "." + viewControllerName),
                let clsType = cls as? UIViewController.Type else {
                completion(false)
                return
            }
            let targetViewController = clsType.init()
            targetViewController.urlParams = urlParams
            self.navigationController().pushViewController(targetViewController, animated: animated)
        }
        
        func open(_ url: String, urlParams: [AnyHashable : Any],
                  exts: [AnyHashable : Any], completion: @escaping (Bool) -> Void) {
            var animated = false
            if exts["animated"] != nil {
                animated = exts["animated"] as! Bool
            }
            
            guard url.hasPrefix("flutterbus://") else {
                //处理 nativebus: 页面
                openNative(url, urlParams: urlParams, exts: exts, animated: animated, completion: completion)
                return
            }
            
            let vc = FLBFlutterViewContainer()
            vc.setName(url, params: urlParams)
            navigationController().pushViewController(vc, animated: animated)
            completion(true)
        }
        
        func present(_ url: String, urlParams: [AnyHashable : Any], exts: [AnyHashable : Any],
                     completion: @escaping (Bool) -> Void) {
            var animated = false
            if exts["animated"] != nil {
                animated = exts["animated"] as! Bool
            }
            let vc = FLBFlutterViewContainer()
            vc.setName(url, params: urlParams)
            navigationController().present(vc, animated: animated) {
                completion(true)
            };
        }
        
        func close(_ uid: String, result: [AnyHashable : Any], exts: [AnyHashable : Any],
                   completion: @escaping (Bool) -> Void) {
            var animated = false
            if exts["animated"] != nil {
                animated = exts["animated"] as! Bool
            }
            let presentedVC = navigationController().presentedViewController
            let vc = presentedVC as? FLBFlutterViewContainer
            if vc?.uniqueIDString() == uid {
                vc?.dismiss(animated: animated, completion: {
                    completion(true)
                })
            } else {
                navigationController().popViewController(animated: animated)
            }
        }
        
        func navigationController() -> UINavigationController {
            let delegate = UIApplication.shared.delegate as! AppDelegate
            let navigationController = delegate.window?.rootViewController as! UINavigationController
            return navigationController;
        }
    }
    

    Flutter_Boost官方给出了FLBPlatform协议默认实现,具体可查看PlatformRouterImp,PlatformRouter在此基础上加了openNative代码

    三、在FlutterBoostDemo module中配置路由页面

    import 'package:flutter/material.dart';
    import 'package:flutter_boost/flutter_boost.dart';
    
    import 'FirstPage.dart';
    
    void main() => runApp(MyApp());
    
    class MyApp extends StatefulWidget {
      @override
      _MyAppState createState() => _MyAppState();
    }
    
    class _MyAppState extends State<MyApp> {
      @override
      void initState() {
        super.initState();
        // 注册Native可以调用的页面
        FlutterBoost.singleton.registerPageBuilders({
          'flutterbus://FirstPage': (pageName, params, _) =>
              FirstPage(params: params),
        });
      }
    
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          title: 'Flutter',
          builder: FlutterBoost.init(),
          home: Container(),
        );
      }
    }
    

    四、Native 打开Flutter页面

    通过FlutterBoostPlugin的open方法打开Flutter页面,代码如下

    import UIKit
    import Foundation
    import flutter_boost
    
    class FirstViewController: UIViewController {
    
        override func viewDidLoad() {
            super.viewDidLoad()
            title = "First Page"
            
            let button = UIButton(frame: CGRect(x: 80, y: 100, width: 200, height: 40))
            button.backgroundColor = .red
            button.setTitle("Native打开Fluter页面", for: UIControl.State.normal)
            button.titleLabel?.font = UIFont.systemFont(ofSize: 13)
            button.setTitleColor(.white, for: UIControl.State.normal)
            button.addTarget(self, action: #selector(openFlutterPage), for: UIControl.Event.touchUpInside)
            view.addSubview(button)
        }
        
        @objc func openFlutterPage() {
            let urlParams = ["startCount": 5] // 传入参数,Flutter可接收
            FlutterBoostPlugin.open("flutterbus://FirstPage", urlParams: urlParams, exts: [:], onPageFinished: { (map) in
               print(map)
            }) { (finished) in
            }
        }
    }
    

    五、Flutter打开Native页面

    Flutter代码如下:

    import 'package:flutter/material.dart';
    import 'package:flutter_boost/flutter_boost.dart';
    
    class FirstPage extends StatefulWidget {
      FirstPage({
        Key key,
        this.params,
      }) : super(key: key);
    
      final Map params; //Native传入
    
      @override
      State<StatefulWidget> createState() {
        _FirstPageState homeState = _FirstPageState();
        homeState.counter = params['startCount'];
        return homeState;
      }
    }
    
    class _FirstPageState extends State<FirstPage> {
      int counter;
    
      void _incrementCounter() {
        setState(() {
          counter++;
        });
      }
    
      void _stopCounter() {
        FlutterBoost.singleton.open("nativebus://SecondViewController",
            urlParams: {"message": "Flutter打开Native页面", "finalCount": counter});
      }
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          body: Center(
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                Row(
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: <Widget>[
                    Text(
                      '当前计数为:',
                    ),
                    Text(
                      '$counter',
                      style: Theme.of(context).textTheme.headline4,
                    ),
                  ],
                ),
                Padding(
                  padding: EdgeInsets.all(12),
                ),
                Text(
                  '点击下面按钮计数加1',
                ),
                FlatButton(onPressed: _incrementCounter, child: Icon(Icons.add)),
              ],
            ),
          ),
          floatingActionButton: FloatingActionButton(
            onPressed: _stopCounter,
            tooltip: 'Stop',
            child: Icon(Icons.stop),
          ),
        );
      }
    }
    

    Native页面代码如下:

    import UIKit
    
    class SecondViewController: UIViewController {    
        
        override func viewDidLoad() {
            super.viewDidLoad()
            title = "Second Page"
            
            var count = 0
            if let params = urlParams as? [String: Any], let counter = params["finalCount"] as? Int {
                count = counter
            }
            
            let label = UILabel(frame: CGRect(x: 80, y: 100, width: 200, height: 40))
            label.text = "最终计数为\(count)"
            label.backgroundColor = .blue
            label.textColor = .white
            view.addSubview(label)
        }
    }
    

    其中urlParams是用UIViewController扩展添加的,代码如下:

    import UIKit
    
    private struct AssociatedKey {
        static var urlParams = "urlParams"
    }
    
    extension UIViewController {
        
        var urlParams: [AnyHashable : Any]? {
            set {
                objc_setAssociatedObject(self,
                                         &AssociatedKey.urlParams,
                                         newValue,
                                         .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
            }
            get {
                var result: [AnyHashable : Any]?
                if let params = objc_getAssociatedObject(self, &AssociatedKey.urlParams) as? [AnyHashable : Any] {
                    result = params
                }
                return result
            }
        }
    }
    

    相关文章

      网友评论

        本文标题:iOS+Flutter--FlutterBoost(二)

        本文链接:https://www.haomeiwen.com/subject/zjcjektx.html