Flutter圈子Flutter中文社区Flutter

Flutter 开发 (1)iOS 下超详细集成 Flutter

2018-12-18  本文已影响40人  ForestSen

iOS 客户端接入 Flutter 实践

目录

背景

一、介绍

Flutter是一款移动应用程序SDK,一份代码可以同时生成iOS和Android两个高性能、高保真的应用程序。

Flutter目标是使开发人员能够交付在不同平台上都感觉自然流畅的高性能应用程序。

目前使用Flutter的APP并不算很多,相关资料并不丰富,介绍现有工程引入Flutter的相关文章也比较少。

Flutter架构

二、搭建 Flutter-iOS 开发环境

1. 获取 Flutter 工程

2. 配置 Flutter 环境变量

(1)说明

(2)添加环境变量(确保路径指向没问题)

export PATH=$HOME/flutter/bin:$PATH
export FLUTTER_ROOT=$HOME/flutter

export PUB_HOSTED_URL=https://pub.flutter-io.cn
export FLUTTER_STORAGE_BASE_URL=https://storage.flutter-io.cn

(3)注意

source ~/.bash_profile

3. 配置基本环境依赖

brew install --HEAD libimobiledevice
brew install ideviceinstaller ios-deploy cocoapods

4. flutter doctor 检测本机环境

1. 说明
2. flutter doctor 检查失败原因
3. 安卓SDK相关环境变量设置
  # android sdk目录,替换为你自己的即可。
  export ANDROID_HOME="/Users/用户名/Documents/android_sdk" 
  export PATH=${PATH}:${ANDROID_HOME}/tools
  export PATH=${PATH}:${ANDROID_HOME}/platform-tools

三、iOS现有项目接入flutter

(1)说明
(2)创建Flutter模块
cd /Users/sen/Desktop/Flutter工程/Flutter_iOS
flutter create -t module flutter_library
(3)创建iOS项目的 Config 文件
(4)Config 文件 内容
#include "../flutter_library/.ios/Flutter/Generated.xcconfig"
ENABLE_BITCODE=NO
#include "Flutter.xcconfig"

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

// 如果使用了Cocoapods,那么需要引入 cocoapods 的config文件,因为如果自定义了config,那么cocoapods 的 config 就不会自动指定了。
#include "Pods/Target Support Files/Pods-Flutter_iOS/Pods-Flutter_iOS.release.xcconfig"
(4)项目中指定使用 config
(5)设置 Flutter 的脚本
"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh" build
(6)修改Flutter脚本
  local derived_dir="${SOURCE_ROOT}/Flutter"
#  if [[ -e "${project_path}/.ios" ]]; then
#    derived_dir="${project_path}/.ios/Flutter"
#  fi
  RunCommand mkdir -p -- "$derived_dir"
  AssertExists "$derived_dir"
(7)引入Flutter编译产物

四、改造iOS工程

(1)AppDelegate.h 改造
#import <UIKit/UIKit.h>
#import <Flutter/Flutter.h>

@interface AppDelegate : FlutterAppDelegate <UIApplicationDelegate, FlutterAppLifeCycleProvider>

@end
(2)AppDelegate.m 改造
#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 handleStatusBarTouches:event];
    }
}
@end
(3)主工程调用Flutter 进行测试
#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 Demo";
    
    [self presentViewController:flutterViewController animated:YES completion:nil];
}
@end

四、运行进行测试

(1)使用 Android Studio 打开 Flutter 模块
(2)运行iOS工程。
Demo 地址

https://github.com/bigsen/Flutter_iOS

注意
下一篇文章

五、相关文章

上一篇 下一篇

猜你喜欢

热点阅读