iOS项目中加入flutter

发布时间 2023-12-20 17:59:40作者: ZhangShengjie

新建一个iOS项目Test

在iOS同级目录下建一个flutter module

flutter create --template module my_flutter

podfile编写如下

# Uncomment the next line to define a global platform for your project
# platform :ios, '9.0'

target 'Test' do
  # Comment the next line if you don't want to use dynamic frameworks
  use_frameworks!
flutter_application_path = '../my_flutter'
load File.join(flutter_application_path, '.ios', 'Flutter', 'podhelper.rb')
install_all_flutter_pods(flutter_application_path)
  # Pods for Test

end

post_install do |installer|
  flutter_post_install(installer) if defined?(flutter_post_install)
end

 使用

  • 直接使用
  1. navigationController?.pushViewController(FlutterViewController(), animated: true)
  • 有交互的使用
  • import UIKit
    import Flutter
    // The following library connects plugins with iOS platform code to this app.
    //import FlutterPluginRegistrant
    
    @UIApplicationMain
    class AppDelegate: FlutterAppDelegate { // More on the FlutterAppDelegate.
        let engines = FlutterEngineGroup(name: "ios_fultter_double", project: nil)
    
      override func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        // Runs the default Dart entrypoint with a default Flutter route.
    //    flutterEngine.run();
        // Connects plugins with iOS platform code to this app.
    //    GeneratedPluginRegistrant.register(with: self.flutterEngine);
        return super.application(application, didFinishLaunchingWithOptions: launchOptions);
      }
    }
    
    
    // Copyright 2021 The Flutter team. All rights reserved.
    // Use of this source code is governed by a BSD-style license that can be
    // found in the LICENSE file.
    
    import Flutter
    import FlutterPluginRegistrant
    import Foundation
    
    /// A FlutterViewController intended for the MyApp widget in the Flutter module.
    ///
    /// This view controller maintains a connection to the Flutter instance and syncs it with the
    /// datamodel.  In practice you should override the other init methods or switch to composition
    /// instead of inheritence.
    class InteractionViewController: FlutterViewController {
        private var channel: FlutterMethodChannel?
    
        init(withEntrypoint entryPoint: String?) {
            let appDelegate: AppDelegate = UIApplication.shared.delegate as! AppDelegate
            let newEngine = appDelegate.engines.makeEngine(withEntrypoint: entryPoint, libraryURI: nil)
            GeneratedPluginRegistrant.register(with: newEngine)
            super.init(engine: newEngine, nibName: nil, bundle: nil)
    
        }
    
       
    
        required init(coder aDecoder: NSCoder) {
            fatalError("init(coder:) has not been implemented")
        }
    
    
        override func viewDidLoad() {
            super.viewDidLoad()
            channel = FlutterMethodChannel(
                name: "ios_fultter_double", binaryMessenger: engine!.binaryMessenger)
            
            let navController = navigationController!
            channel!.setMethodCallHandler { (call: FlutterMethodCall, result: @escaping FlutterResult) in
                if call.method == "incrementCount" {
                    result(nil)
                } else if call.method == "next" {
                    navController.pushViewController(FlutterViewController(), animated: true)
                    result(nil)
                } else {
                    result(FlutterMethodNotImplemented)
                }
            }
        }
    }
    // Copyright 2021 The Flutter team. All rights reserved.
    // Use of this source code is governed by a BSD-style license that can be
    // found in the LICENSE file.
    
    import 'package:flutter/material.dart';
    import 'package:flutter/services.dart';
    
    void main() => runApp(const MyApp(color: Colors.blue));
    
    @pragma('vm:entry-point')
    void topMain() => runApp(const MyApp(color: Colors.green));
    
    @pragma('vm:entry-point')
    void bottomMain() => runApp(const MyApp(color: Colors.purple));
    
    class MyApp extends StatelessWidget {
      const MyApp({super.key, required this.color});
    
      final MaterialColor color;
    
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          title: 'Flutter Demo',
          theme: ThemeData(
            colorSchemeSeed: color,
            useMaterial3: true,
            appBarTheme: AppBarTheme(
              backgroundColor: color,
              foregroundColor: Colors.white,
              elevation: 8,
            ),
          ),
          home: const MyHomePage(title: 'Flutter Demo Home Page'),
        );
      }
    }
    
    class MyHomePage extends StatefulWidget {
      const MyHomePage({super.key, required this.title});
      final String title;
    
      @override
      State<MyHomePage> createState() => _MyHomePageState();
    }
    
    class _MyHomePageState extends State<MyHomePage> {
      int? _counter = 0;
      late MethodChannel _channel;
    
      @override
      void initState() {
        super.initState();
        _channel = const MethodChannel('ios_fultter_double');
        _channel.setMethodCallHandler((call) async {
          if (call.method == "setCount") {
            // A notification that the host platform's data model has been updated.
            setState(() {
              _counter = call.arguments as int?;
            });
          } else {
            throw Exception('not implemented ${call.method}');
          }
        });
      }
    
      void _incrementCounter() {
        // Mutations to the data model are forwarded to the host platform.
        _channel.invokeMethod<void>("incrementCount", _counter);
      }
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            title: Text(widget.title),
          ),
          body: Center(
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                const Text(
                  'You have pushed the button this many times:',
                ),
                Text(
                  '$_counter',
                  style: Theme.of(context).textTheme.headlineMedium,
                ),
                TextButton(
                  onPressed: _incrementCounter,
                  child: const Text('Add'),
                ),
                TextButton(
                  onPressed: () {
                    _channel.invokeMethod<void>("next", _counter);
                  },
                  child: const Text('Next'),
                ),
                ElevatedButton(
                  onPressed: () async {
                    // Use the url_launcher plugin to open the Flutter docs in
                    // a browser.
                    final url = Uri.parse('https://flutter.dev/docs');
                  },
                  child: const Text('Open Flutter Doc11s'),
                ),
              ],
            ),
          ),
        );
      }
    }