preface

Flutter is a promising framework, but currently there are not many APPS using Flutter, and there are not many relevant materials. There are also few articles about the introduction of Flutter in existing projects. The project was started from scratch, and the operation of introducing Flutter was relatively simple, but the introduction of Flutter in the existing project required a lot of energy and time. Here is a summary article I wrote after the introduction of Flutter in the existing iOS project.

Construction of Flutter environment

The first step is to build a Flutter environment. I have written an article about building a Flutter-iOS development environment. You can refer to this article at github.com/flutter/flu… Relatively simple, not to repeat here.

Existing iOS projects introduce Flutter

Create a Flutter Module

Create a Flutter Module to obtain Generated. Xcconfig and framework in the FLUTTER app

cd some/path/
$ flutter create -t module my_flutter
Copy the code

You can also use

flutter create app
Copy the code

Create a Flutter app that contains Generated. Xcconfig and framework

2. Create a configuration file

According to the official website, three configuration files need to be established in the project: Flutter. Xcconfig, debug. xcconfig, release. xcconfig in the folder corresponding to the XCode project, right click, select New File, and select create xcConfig as shown in the picture:

inFlutter.xcconfigFill in:
// Enter the path Generated. Xcconfig of flutter Module created earlier#include ".. /.. /my_flutter/.ios/Flutter/Generated.xcconfig"
ENABLE_BITCODE=NO
Copy the code
inDebug.xcconfigFill in:
#include ".. /Flutter/Flutter.xcconfig"

Copy the code

Fill in the Release. Xcconfig:

#include ".. /Flutter/Flutter.xcconfig"
FLUTTER_BUILD_MODE=release
Copy the code

If your project is managed by Cocoapods, you need to add the pod path to debug. xcconfig and release.xcconfig:

For example the xcconfig

#include "Flutter.xcconfig"
#include "project path /Pods/Target Support Files/******. Release. Xcconfig "// POD path
FLUTTER_BUILD_MODE=release
Copy the code

After you have these xcConfig files ready, you need to go to the Configuration option in the XCode PROJECT and select the corresponding Target as the previous XCconfig file. Debug uses debug.xcconfig, Release uses release.xcconfig

Note: When Archive is packaged, either Debug or Release packages need to be switched to release.xcconfig, otherwise an error will be reported.

3. Introduce a build phase for compiling Dart

Create a Run Script in the Build Phase of the project, which is used to Run the Script during compilation. The establishment method is shown as follows:

After the Run Script is set to Target dependencies, and after the Check Pods Manifest.lock dependencies:

In the script box, fill in the following code to import the Xcode_backend script from Flutter:

"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh" build
Copy the code

As shown in figure:

Build and add Framework

Build (Command+B) in XCode. When “Build Success” is prompted, a Flutter folder will be generated in the iOS project folder. Add it to the project directory, recommended alongside the directory where xcconfig is located,

Right-click on the project directory and select Add Files to ‘XXX’. Options select Create Groups to Add the generated Flutter folder. Note however: There is a flutter_assets file in the Flutter directory, which cannot be added by creating groups. You can only add Options of Creat Folder References, otherwise the Flutter page will be blank and cannot be rendered. You can delete Flutter_assets and add them again using Creat Folder References.

After adding the Flutter folder, go to Embeded Binaries and add app. framework and Flutter

Five, AppDelegate transformation

The Flutter needs to interact with the APP, and the AppDelegate needs to be modified:

In the appdelegate. h file:

#import <Flutter/Flutter.h>

@interface AppDelegate : FlutterAppDelegate <UIApplicationDelegate, FlutterAppLifeCycleProvider>

@end
Copy the code

In the appdelegate. m file:

#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];
}

Copy the code

Create a FlutterViewController

The main configuration is almost complete, just implement the business code for Flutter in Main.dart

main.dart

    self.flutterViewController = [[FlutterViewController alloc] initWithProject:nil nibName:nil bundle:nil];
    [self.navigationController pushViewController:self.flutterViewController animated:YES];
Copy the code

After the language

At this point, the existing iOS project introduces Flutter. Some details need to be modified according to the scenario, such as the data communication between Flutter and Native.