iOS项目中集成flutter

创建iOS项目

这里我们先创建一个空的iOS项目来模拟已有的项目,取名叫iOS_demo

创建flutter模块

进入你的项目同一层目录,创建flutter模块

flutter create -t module flutter_lab
文件目录.png

关闭Bitcode

Flutter混合开发还不支持Bitcode,所以在iOS工程检查项目并关闭Bitcode

Bitcode.png

iOS项目相关配置

image.png

Flutter.xcconfig 内容

#include "../flutter_lab/.ios/Flutter/Generated.xcconfig"
ENABLE_BITCODE=NO

Debug.xcconfig 内容 (对应的名字换成自己)

#include "Flutter.xcconfig"

// 如果使用了Cocoapods,那么需要引入 cocoapods 的config文件,因为如果自定义了config,那么cocoapods 的 config 就不会自动指定了。
#include "Pods/Target Support Files/Pods-iOS_demo/Pods-iOS_demo.debug.xcconfig"

Release.xcconfig

#include "Flutter.xcconfig"
FLUTTER_BUILD_MODE=release

// 如果使用了Cocoapods,那么需要引入 cocoapods 的config文件,因为如果自定义了config,那么cocoapods 的 config 就不会自动指定了。
#include "Pods/Target Support Files/Pods-iOS_demo/Pods-iOS_demo.release.xcconfig"

指定 config 文件,Debug 对应 Debug,Release 对应 Release

image.png

增加 Flutter 的脚本

image.png
image.png
"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh" build

修改Flutter脚本

在下载的flutter SDK中找到xcode_backend文件

image.png

注释这段脚本

image.png

编译iOS项目,在项目目录下会生成一个flutter文件夹


image.png

右键项目 - Add Files to 'xxx' 【Options先选Create groups】,选择Flutter目录

image.png

但是flutter_assets 并不能使用Create groups 的方式添加,只能使用Creat folder references 的方式添加进Xcode项目内,否则跳转flutter会页面渲染失败(页面空白)。


image.png

文件夹再Add Files to 'xxx',选择Creat folder references ;最终如下图


image.png
image.png

iOS项目改造

#import <UIKit/UIKit.h>
#import <Flutter/Flutter.h>

@interface AppDelegate : FlutterAppDelegate <UIApplicationDelegate, FlutterAppLifeCycleProvider>

@property (strong, nonatomic) UIWindow *window;

@end

#import "AppDelegate.h"

@interface AppDelegate ()

@end

@implementation AppDelegate
{
    FlutterPluginAppLifeCycleDelegate *_lifeCycleDelegate;
}

- (instancetype)init {
    if (self = [super init]) {
        _lifeCycleDelegate = [[FlutterPluginAppLifeCycleDelegate alloc] init];
    }
    return self;
}

- (BOOL)application:(UIApplication*)application
didFinishLaunchingWithOptions:(NSDictionary*)launchOptions {
    return [_lifeCycleDelegate application:application didFinishLaunchingWithOptions:launchOptions];
}

- (void)applicationDidEnterBackground:(UIApplication*)application {
    [_lifeCycleDelegate applicationDidEnterBackground:application];
}

- (void)applicationWillEnterForeground:(UIApplication*)application {
    [_lifeCycleDelegate applicationWillEnterForeground:application];
}

- (void)applicationWillResignActive:(UIApplication*)application {
    [_lifeCycleDelegate applicationWillResignActive:application];
}

- (void)applicationDidBecomeActive:(UIApplication*)application {
    [_lifeCycleDelegate applicationDidBecomeActive:application];
}

- (void)applicationWillTerminate:(UIApplication*)application {
    [_lifeCycleDelegate applicationWillTerminate:application];
}

- (void)application:(UIApplication*)application
didRegisterUserNotificationSettings:(UIUserNotificationSettings*)notificationSettings {
    [_lifeCycleDelegate application:application
didRegisterUserNotificationSettings:notificationSettings];
}

- (void)application:(UIApplication*)application
didRegisterForRemoteNotificationsWithDeviceToken:(NSData*)deviceToken {
    [_lifeCycleDelegate application:application
didRegisterForRemoteNotificationsWithDeviceToken:deviceToken];
}

- (void)application:(UIApplication*)application
didReceiveRemoteNotification:(NSDictionary*)userInfo
fetchCompletionHandler:(void (^)(UIBackgroundFetchResult result))completionHandler {
    [_lifeCycleDelegate application:application
       didReceiveRemoteNotification:userInfo
             fetchCompletionHandler:completionHandler];
}

- (BOOL)application:(UIApplication*)application
            openURL:(NSURL*)url
            options:(NSDictionary<UIApplicationOpenURLOptionsKey, id>*)options {
    return [_lifeCycleDelegate application:application openURL:url options:options];
}

- (BOOL)application:(UIApplication*)application handleOpenURL:(NSURL*)url {
    return [_lifeCycleDelegate application:application handleOpenURL:url];
}

- (BOOL)application:(UIApplication*)application
            openURL:(NSURL*)url
  sourceApplication:(NSString*)sourceApplication
         annotation:(id)annotation {
    return [_lifeCycleDelegate application:application
                                   openURL:url
                         sourceApplication:sourceApplication
                                annotation:annotation];
}

- (void)application:(UIApplication*)application
performActionForShortcutItem:(UIApplicationShortcutItem*)shortcutItem
  completionHandler:(void (^)(BOOL succeeded))completionHandler NS_AVAILABLE_IOS(9_0) {
    [_lifeCycleDelegate application:application
       performActionForShortcutItem:shortcutItem
                  completionHandler:completionHandler];
}

- (void)application:(UIApplication*)application
handleEventsForBackgroundURLSession:(nonnull NSString*)identifier
  completionHandler:(nonnull void (^)(void))completionHandler {
    [_lifeCycleDelegate application:application
handleEventsForBackgroundURLSession:identifier
                  completionHandler:completionHandler];
}

- (void)application:(UIApplication*)application
performFetchWithCompletionHandler:(void (^)(UIBackgroundFetchResult result))completionHandler {
    [_lifeCycleDelegate application:application performFetchWithCompletionHandler:completionHandler];
}

- (void)addApplicationLifeCycleDelegate:(NSObject<FlutterPlugin>*)delegate {
    [_lifeCycleDelegate addDelegate:delegate];
}

#pragma mark - Flutter
// Returns the key window's rootViewController, if it's a FlutterViewController.
// Otherwise, returns nil.
- (FlutterViewController*)rootFlutterViewController {
    UIViewController* viewController = [UIApplication sharedApplication].keyWindow.rootViewController;
    if ([viewController isKindOfClass:[FlutterViewController class]]) {
        return (FlutterViewController*)viewController;
    }
    return nil;
}

- (void)touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event {
    [super touchesBegan:touches withEvent:event];
    
    // Pass status bar taps to key window Flutter rootViewController.
    if (self.rootFlutterViewController != nil) {
        [self.rootFlutterViewController handleStatusBarTouche

测试

    #import "ViewController.h"
    #import <Flutter/FlutterViewController.h>
    
    @interface ViewController ()
    
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        // Do any additional setup after loading the view, typically from a nib.
    }
    
    - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
        FlutterViewController* flutterViewController = [[FlutterViewController alloc] initWithProject:nil nibName:nil bundle:nil];
        flutterViewController.navigationItem.title = @"Flutter";
        [self presentViewController:flutterViewController animated:YES completion:nil];
    }
    
    @end

推荐阅读更多精彩内容