创建iOS项目
这里我们先创建一个空的iOS项目来模拟已有的项目,取名叫iOS_demo
创建flutter模块
进入你的项目同一层目录,创建flutter模块
flutter create -t module flutter_lab
关闭Bitcode
Flutter混合开发还不支持Bitcode,所以在iOS工程检查项目并关闭Bitcode
iOS项目相关配置
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
增加 Flutter 的脚本
"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh" build
修改Flutter脚本
在下载的flutter SDK中找到xcode_backend文件
注释这段脚本
编译iOS项目,在项目目录下会生成一个flutter文件夹
右键项目 - Add Files to 'xxx' 【Options先选Create groups】,选择Flutter目录
但是flutter_assets 并不能使用Create groups 的方式添加,只能使用Creat folder references 的方式添加进Xcode项目内,否则跳转flutter会页面渲染失败(页面空白)。
文件夹再Add Files to 'xxx',选择Creat folder references ;最终如下图
iOS项目改造
#import
#import
@interface AppDelegate : FlutterAppDelegate
@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*)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*)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
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)touchesBegan:(NSSet *)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