Commit 854b8d32 authored by Jidong Chen's avatar Jidong Chen

去掉截图,运行成功

parent 39cbcbc7
/Users/jidong/Documents/opensource/flutter_boost
\ No newline at end of file
/Users/jidong/Documents/projects/Flutter/flutter_boost
\ No newline at end of file
/Users/jidong/.pub-cache/hosted/pub.dartlang.org/xservice_kit-0.0.27
\ No newline at end of file
/Users/jidong/.pub-cache/hosted/pub.dartlang.org/xservice_kit-0.0.29
\ No newline at end of file
......@@ -8,20 +8,20 @@ PODS:
DEPENDENCIES:
- Flutter (from `.symlinks/flutter/ios`)
- flutter_boost (from `/Users/jidong/Documents/opensource/flutter_boost/ios`)
- xservice_kit (from `/Users/jidong/.pub-cache/hosted/pub.dartlang.org/xservice_kit-0.0.27/ios`)
- flutter_boost (from `/Users/jidong/Documents/projects/Flutter/flutter_boost/ios`)
- xservice_kit (from `/Users/jidong/.pub-cache/hosted/pub.dartlang.org/xservice_kit-0.0.29/ios`)
EXTERNAL SOURCES:
Flutter:
:path: ".symlinks/flutter/ios"
flutter_boost:
:path: "/Users/jidong/Documents/opensource/flutter_boost/ios"
:path: "/Users/jidong/Documents/projects/Flutter/flutter_boost/ios"
xservice_kit:
:path: "/Users/jidong/.pub-cache/hosted/pub.dartlang.org/xservice_kit-0.0.27/ios"
:path: "/Users/jidong/.pub-cache/hosted/pub.dartlang.org/xservice_kit-0.0.29/ios"
SPEC CHECKSUMS:
Flutter: 9d0fac939486c9aba2809b7982dfdbb47a7b0296
flutter_boost: 24249d12d924d858cf445a84949484bc08bca000
flutter_boost: 6a083f2f1b67f9b08724d6c4b280a099d1b40797
xservice_kit: a86c64372b3e41e7d8e9b1a0b9139866680f525c
PODFILE CHECKSUM: 2a757a7bdc03b37a2814666652fdff1cf694243f
......
......@@ -19,6 +19,12 @@
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
DemoRouter *router = [DemoRouter sharedRouter];
[FlutterBoostPlugin.sharedInstance startFlutterWithPlatform:router
onStart:^(FlutterEngine *fvc) {
}];
self.window = [[UIWindow alloc] initWithFrame: [UIScreen mainScreen].bounds];
......@@ -37,16 +43,13 @@
UITabBarController *tabVC = [[UITabBarController alloc] init];
UINavigationController *rvc = [[UINavigationController alloc] initWithRootViewController:tabVC];
DemoRouter *router = [DemoRouter sharedRouter];
router.navigationController = rvc;
tabVC.viewControllers = @[vc,fvc];
[FlutterBoostPlugin.sharedInstance startFlutterWithPlatform:router
onStart:^(FlutterViewController *fvc) {
}];
self.window.rootViewController = rvc;
......
......@@ -23,13 +23,13 @@
*/
#import <Foundation/Foundation.h>
#import "FLBFlutterViewProvider.h"
#import "FLBFlutterProvider.h"
NS_ASSUME_NONNULL_BEGIN
#if RELEASE_1_0
@interface FLBFlutterEngine : NSObject<FLBFlutterViewProvider>
@interface FLBFlutterEngine : NSObject<FLBFlutterProvider>
@end
#endif
......
......@@ -24,13 +24,13 @@
#import "FLBFlutterEngine.h"
#import <Flutter/Flutter.h>
#import "FLBFlutterViewControllerAdaptor.h"
#import "FLBFlutterViewContainer.h"
#if RELEASE_1_0
@interface FLBFlutterEngine()
@property (nonatomic,strong) FLBFlutterViewControllerAdaptor *viewController;
@property (nonatomic,strong) FlutterEngine *engine;
@property (nonatomic,strong) FLBFlutterViewContainer *dummy;
@end
@implementation FLBFlutterEngine
......@@ -43,15 +43,14 @@
if (self = [super init]) {
_engine = [[FlutterEngine alloc] initWithName:@"io.flutter" project:nil];
[_engine runWithEntrypoint:nil];
_viewController = [[FLBFlutterViewControllerAdaptor alloc] initWithEngine:_engine
_dummy = [[FLBFlutterViewContainer alloc] initWithEngine:_engine
nibName:nil
bundle:nil];
[_viewController view];
Class clazz = NSClassFromString(@"GeneratedPluginRegistrant");
if (clazz) {
if ([clazz respondsToSelector:NSSelectorFromString(@"registerWithRegistry:")]) {
[clazz performSelector:NSSelectorFromString(@"registerWithRegistry:")
withObject:_viewController];
withObject:_engine];
}
}
}
......@@ -60,23 +59,14 @@
#pragma clang diagnostic pop
}
- (FlutterViewController *)viewController
{
return _viewController;
}
- (void)pause
{
//TODO: [[_engine.get() lifecycleChannel] sendMessage:@"AppLifecycleState.paused"];
[self.viewController boost_viewWillDisappear:NO];
[self.viewController boost_viewDidDisappear:NO];
[[_engine lifecycleChannel] sendMessage:@"AppLifecycleState.pause"];
}
- (void)resume
{
//TODO: [[_engine.get() lifecycleChannel] sendMessage:@"AppLifecycleState.resumed"];
[self.viewController boost_viewWillAppear:NO];
[self.viewController boost_viewDidAppear:NO];
[[_engine lifecycleChannel] sendMessage:@"AppLifecycleState.resume"];
}
- (void)inactive
......@@ -84,10 +74,32 @@
[[_engine lifecycleChannel] sendMessage:@"AppLifecycleState.inactive"];
}
- (void)setAccessibilityEnable:(BOOL)enable
- (FlutterEngine *)engine
{
return _engine;
}
- (void)atacheToViewController:(FlutterViewController *)vc
{
if(_engine.viewController != vc){
_engine.viewController = vc;
}
}
- (void)detach
{
if(_engine.viewController != _dummy){
_engine.viewController = _dummy;
}
}
- (void)prepareEngineIfNeeded
{
self.viewController.accessibilityEnable = enable;
[self detach];
[_dummy surfaceUpdated:YES];
}
@end
#endif
/*
* The MIT License (MIT)
*
* Copyright (c) 2019 Alibaba Group
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#import "FLBFlutterEngineOld.h"
#import "FLBFlutterViewControllerAdaptor.h"
#import <objc/runtime.h>
@interface FLBFlutterEngineOld()
@property (nonatomic,strong) FLBFlutterViewControllerAdaptor *viewController;
@end
@implementation FLBFlutterEngineOld
- (instancetype)initWithPlatform:(id<FLBPlatform>)platform
{
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
if (self = [super init]) {
Class class = [FLBFlutterViewControllerAdaptor class];
SEL originalSelector = @selector(onAccessibilityStatusChanged:);
SEL swizzledSelector = @selector(fixed_onAccessibilityStatusChanged:);
Method originalMethod = class_getInstanceMethod(class, originalSelector);
Method swizzledMethod = class_getInstanceMethod(class, swizzledSelector);
method_exchangeImplementations(originalMethod, swizzledMethod);
_viewController = [FLBFlutterViewControllerAdaptor new];
if([platform respondsToSelector:@selector(accessibilityEnable)]){
_viewController.accessibilityEnable = [platform accessibilityEnable];
}else{
_viewController.accessibilityEnable = YES;
}
[_viewController view];
Class clazz = NSClassFromString(@"GeneratedPluginRegistrant");
if (clazz) {
if ([clazz respondsToSelector:NSSelectorFromString(@"registerWithRegistry:")]) {
[clazz performSelector:NSSelectorFromString(@"registerWithRegistry:")
withObject:_viewController];
}
}
}
return self;
#pragma clang diagnostic pop
}
- (FlutterViewController *)viewController
{
return _viewController;
}
- (void)pause
{
[self.viewController boost_viewWillDisappear:NO];
[self.viewController boost_viewDidDisappear:NO];
}
- (void)resume
{
[self.viewController boost_viewWillAppear:NO];
[self.viewController boost_viewDidAppear:NO];
}
- (void)inactive
{
NSString *channel = @"flutter/lifecycle";
NSString *message = @"AppLifecycleState.inactive";
NSData *data = [[FlutterStringCodec sharedInstance] encode:message];
[self.viewController sendOnChannel:channel message:data];
}
- (void)resumeFlutterOnly
{
NSString *channel = @"flutter/lifecycle";
NSString *message = @"AppLifecycleState.resumed";
NSData *data = [[FlutterStringCodec sharedInstance] encode:message];
[self.viewController sendOnChannel:channel message:data];
}
- (void)setAccessibilityEnable:(BOOL)enable
{
self.viewController.accessibilityEnable = enable;
}
@end
......@@ -25,21 +25,23 @@
#import <Foundation/Foundation.h>
@class FlutterViewController;
@class FlutterEngine;
NS_ASSUME_NONNULL_BEGIN
#define RELEASE_1_0 0
#define RELEASE_1_0 1
@protocol FLBFlutterViewProvider <NSObject>
@protocol FLBFlutterProvider <NSObject>
@required
- (void)setAccessibilityEnable:(BOOL)enable;
- (BOOL)accessibilityEnable;
- (FlutterViewController *)viewController;
- (FlutterEngine *)engine;
- (void)atacheToViewController:(FlutterViewController *)vc;
- (void)detach;
- (void)pause;
- (void)resume;
- (void)inactive;
- (void)prepareEngineIfNeeded;
@end
NS_ASSUME_NONNULL_END
......@@ -23,14 +23,16 @@
*/
#import <Foundation/Foundation.h>
#import "FLBFlutterViewProvider.h"
#import "FLBFlutterProvider.h"
#import "FLBPlatform.h"
NS_ASSUME_NONNULL_BEGIN
@interface FLBFlutterEngineOld : NSObject<FLBFlutterViewProvider>
@interface FLBFlutterProviderFactory : NSObject
- (instancetype)initWithPlatform:(id<FLBPlatform>)platform;
- (id<FLBFlutterProvider>)createViewProvider;
- (id<FLBFlutterProvider>)createViewProviderWithPlatform:(id<FLBPlatform>)platform;
@end
......
......@@ -22,18 +22,21 @@
* THE SOFTWARE.
*/
#import <Foundation/Foundation.h>
#import "FLBFlutterViewProvider.h"
#import "FLBFlutterProviderFactory.h"
#import "FLBFlutterEngine.h"
#import "FLBPlatform.h"
NS_ASSUME_NONNULL_BEGIN
@interface FLBViewProviderFactory : NSObject
@implementation FLBFlutterProviderFactory
- (id<FLBFlutterViewProvider>)createViewProvider;
- (id<FLBFlutterViewProvider>)createViewProviderWithPlatform:(id<FLBPlatform>)platform;
- (id<FLBFlutterProvider>)createViewProviderWithPlatform:(id<FLBPlatform>)platform
{
return [FLBFlutterEngine new];
}
@end
- (id<FLBFlutterProvider>)createViewProvider
{
return [FLBFlutterEngine new];
}
NS_ASSUME_NONNULL_END
@end
/*
* The MIT License (MIT)
*
* Copyright (c) 2019 Alibaba Group
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#import <Flutter/Flutter.h>
NS_ASSUME_NONNULL_BEGIN
@interface FLBFlutterViewControllerAdaptor : FlutterViewController
- (void)boost_viewWillAppear:(BOOL)animated;
- (void)boost_viewDidAppear:(BOOL)animated;
- (void)boost_viewWillDisappear:(BOOL)animated;
- (void)boost_viewDidDisappear:(BOOL)animated;
@property (nonatomic,assign) BOOL accessibilityEnable;
@end
NS_ASSUME_NONNULL_END
/*
* The MIT License (MIT)
*
* Copyright (c) 2019 Alibaba Group
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#import "FLBFlutterViewControllerAdaptor.h"
#import <objc/runtime.h>
@interface FLBFlutterViewControllerAdaptor ()
@end
@implementation FLBFlutterViewControllerAdaptor
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor whiteColor];
// Do any additional setup after loading the view.
}
- (void)viewWillAppear:(BOOL)animated
{
//Left blank intentionally.
}
- (void)viewDidAppear:(BOOL)animated
{
//Left blank intentionally.
}
- (void)viewWillDisappear:(BOOL)animated
{
[[UIApplication sharedApplication] sendAction:@selector(resignFirstResponder) to:nil from:nil forEvent:nil];
//Avoid super call intentionally.
}
- (void)viewDidDisappear:(BOOL)animated
{
//Avoid super call intentionally.
[[[UIApplication sharedApplication] keyWindow] endEditing:YES];
}
- (void)boost_viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
}
- (void)boost_viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
}
- (void)boost_viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
}
- (void)boost_viewDidDisappear:(BOOL)animated
{
[super viewDidDisappear:animated];
}
- (UIEdgeInsets)paddingEdgeInsets{
UIEdgeInsets edgeInsets = UIEdgeInsetsZero;
if (@available(iOS 11, *)) {
edgeInsets = UIEdgeInsetsMake(0, self.view.safeAreaInsets.left, self.view.safeAreaInsets.bottom, self.view.safeAreaInsets.right);
} else {
edgeInsets = UIEdgeInsetsZero;
}
return edgeInsets;
}
- (void)installSplashScreenViewIfNecessary {
//Override this to avoid unnecessary splash Screen.
}
- (void)fixed_onAccessibilityStatusChanged:(NSNotification*)notification {
if(self.accessibilityEnable){
[self fixed_onAccessibilityStatusChanged:notification];
}
}
@end
/*
* The MIT License (MIT)
*
* Copyright (c) 2019 Alibaba Group
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#import "FLBViewProviderFactory.h"
#import "FLBFlutterEngine.h"
#import "FLBFlutterEngineOld.h"
#import "FLBPlatform.h"
@implementation FLBViewProviderFactory
- (id<FLBFlutterViewProvider>)createViewProviderWithPlatform:(id<FLBPlatform>)platform
{
#if RELEASE_1_0
return [FLBFlutterEngine new];
#else
return [[FLBFlutterEngineOld alloc] initWithPlatform:platform];
#endif
}
- (id<FLBFlutterViewProvider>)createViewProvider
{
#if RELEASE_1_0
return [FLBFlutterEngine new];
#else
return [FLBFlutterEngineOld new];
#endif
}
@end
......@@ -26,17 +26,19 @@
#import <Flutter/Flutter.h>
#import "FLBPlatform.h"
#import "FlutterBoost.h"
#import "FLBFlutterProvider.h"
NS_ASSUME_NONNULL_BEGIN
@interface FLBFlutterApplication : NSObject
@property (nonatomic,strong) id<FLBPlatform> platform;
- (id<FLBFlutterProvider>)flutterProvider;
#pragma mark - Getters
- (void)setAccessibilityEnable:(BOOL)enable;
+ (FLBFlutterApplication *)sharedApplication;
- (void)startFlutterWithPlatform:(id<FLBPlatform>)platform
onStart:(void (^)(FlutterViewController *))callback;
onStart:(void (^)(FlutterEngine * _Nonnull))callback;
- (FlutterViewController *)flutterViewController;
#pragma mark - Container Management
......
......@@ -25,15 +25,14 @@
#import "FLBFlutterApplication.h"
#import "FlutterBoost.h"
#import "FLBFlutterViewContainerManager.h"
#import "FLBViewProviderFactory.h"
#import "FLBFlutterProviderFactory.h"
@interface FLBFlutterApplication()
@property (nonatomic,strong) FLBFlutterViewContainerManager *manager;
@property (nonatomic,strong) id<FLBFlutterViewProvider> viewProvider;
@property (nonatomic,strong) id<FLBFlutterProvider> viewProvider;
@property (nonatomic,strong) NSMutableDictionary *pageBuilders;
@property (nonatomic,copy) FLBPageBuilder defaultPageBuilder;
@property (nonatomic,assign) BOOL isRendering;
@property (nonatomic,assign) BOOL isRunning;
@end
......@@ -55,17 +54,20 @@
return _isRunning;
}
- (id)flutterProvider
{
return _viewProvider;
}
- (void)startFlutterWithPlatform:(id<FLBPlatform>)platform
onStart:(void (^)(FlutterViewController * _Nonnull))callback
onStart:(void (^)(FlutterEngine * _Nonnull))callback
{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
self.platform = platform;
self.viewProvider = [[FLBViewProviderFactory new] createViewProviderWithPlatform:platform];
[self.viewProvider resume];
self.isRendering = YES;
self.viewProvider = [[FLBFlutterProviderFactory new] createViewProviderWithPlatform:platform];
self.isRunning = YES;
if(callback) callback(self.viewProvider.viewController);
if(callback) callback(self.viewProvider.engine);
});
}
......@@ -88,11 +90,6 @@
return [self flutterViewController].view;
}
- (FlutterViewController *)flutterViewController
{
return self.viewProvider.viewController;
}
- (BOOL)contains:(FLBFlutterViewContainer *)vc
{
......@@ -117,22 +114,12 @@
- (void)pause
{
if(!_isRendering) return;
[self.viewProvider pause];
_isRendering = NO;
}
- (void)resume
{
if(_isRendering) return;
[self.viewProvider resume];
_isRendering = YES;
}
- (void)inactive
......@@ -140,10 +127,9 @@
[self.viewProvider inactive];
}
- (void)setAccessibilityEnable:(BOOL)enable
- (FlutterViewController *)flutterViewController
{
[self.viewProvider setAccessibilityEnable:enable];
return self.flutterProvider.engine.viewController;
}
@end
......@@ -35,7 +35,7 @@ typedef FLBFlutterViewContainer * (^FLBPageBuilder)(NSString *name,NSDictionary
+ (instancetype)sharedInstance;
- (void)startFlutterWithPlatform:(id<FLBPlatform>)platform onStart:(void (^)(FlutterViewController *))callback;
- (void)startFlutterWithPlatform:(id<FLBPlatform>)platform onStart:(void (^)(FlutterEngine *))callback;
#pragma mark - Some properties.
- (BOOL)isRunning;
......
......@@ -70,7 +70,7 @@
- (void)startFlutterWithPlatform:(id<FLBPlatform>)platform
onStart:(void (^)(FlutterViewController *))callback;
onStart:(void (^)(FlutterEngine *))callback;
{
[FLBFlutterApplication.sharedApplication startFlutterWithPlatform:platform
onStart:callback];
......@@ -101,9 +101,4 @@
[_resultMediator removeHandlerForKey:vcid];
}
- (void)setAccessibilityEnable:(BOOL)enable
{
[[FLBFlutterApplication sharedApplication] setAccessibilityEnable:enable];
}
@end
......@@ -24,10 +24,11 @@
#import <UIKit/UIKit.h>
#import "FLBViewControllerResultHandler.h"
#import <Flutter/Flutter.h>
NS_ASSUME_NONNULL_BEGIN
@interface FLBFlutterViewContainer : UIViewController<FLBViewControllerResultHandler>
@interface FLBFlutterViewContainer : FlutterViewController<FLBViewControllerResultHandler>
@property (nonatomic,copy,readonly) NSString *name;
@property (nonatomic,strong,readonly) NSDictionary *params;
......@@ -41,6 +42,8 @@ NS_ASSUME_NONNULL_BEGIN
- (void)flutterViewDidAppear:(NSDictionary *)params;
- (void)surfaceUpdated:(BOOL)appeared;
@end
NS_ASSUME_NONNULL_END
......@@ -29,6 +29,7 @@
#import "FLBMemoryInspector.h"
#import "Service_NavigationService.h"
#import "FlutterBoostConfig.h"
#import "FLBFlutterViewContainerManager.h"
#define FLUTTER_VIEW [FLBFlutterApplication sharedApplication].flutterViewController.view
#define FLUTTER_VC [FLBFlutterApplication sharedApplication].flutterViewController
......@@ -37,9 +38,7 @@
@interface FLBFlutterViewContainer ()
@property (nonatomic,copy,readwrite) NSString *name;
@property (nonatomic,strong,readwrite) NSDictionary *params;
@property (nonatomic,strong) UIImageView *screenShotView;
@property (nonatomic,assign) long long identifier;
@property (nonatomic,assign) BOOL interactiveGestureActive;
@end
@implementation FLBFlutterViewContainer
......@@ -76,7 +75,6 @@ static NSUInteger kInstanceCounter = 0;
{
kInstanceCounter--;
if([self.class instanceCounter] == 0){
[[FLBStackCache sharedInstance] clear];
[[FLBFlutterApplication sharedApplication] pause];
}
}
......@@ -102,7 +100,10 @@ static NSUInteger kInstanceCounter = 0;
- (instancetype)init
{
if(self = [super init]){
[FLUTTER_APP.flutterProvider prepareEngineIfNeeded];
if(self = [super initWithEngine:FLUTTER_APP.flutterProvider.engine
nibName:nil
bundle:nil]){
[self _setup];
}
return self;
......@@ -122,12 +123,7 @@ static NSUInteger kInstanceCounter = 0;
- (void)flutterViewDidShow:(NSNotification *)notification
{
__weak typeof(self) weakSelf = self;
if([notification.object isEqual: self.uniqueIDString]){
dispatch_async(dispatch_get_main_queue(), ^{
[weakSelf showFlutterView];
});
}
}
- (void)dealloc
......@@ -150,140 +146,28 @@ static NSUInteger kInstanceCounter = 0;
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = UIColor.whiteColor;
self.screenShotView = [[UIImageView alloc] initWithFrame:self.view.bounds];
self.screenShotView.backgroundColor = [UIColor whiteColor];
[self.view addSubview:self.screenShotView];
}
#pragma mark - ScreenShots
- (UIImage *)takeScreenShot
{
CGFloat scale = 1;
switch ([FLBMemoryInspector.sharedInstance currentCondition]) {
case FLBMemoryConditionNormal:
scale = 2;
break;
case FLBMemoryConditionLowMemory:
scale = 1;
break;
case FLBMemoryConditionExtremelyLow:
scale = 0.75;
break;
case FLBMemoryConditionAboutToDie:
return [UIImage new];
break;
case FLBMemoryConditionUnknown:
if([[FLBMemoryInspector sharedInstance] smallMemoryDevice]){
scale = 1;
}else{
scale = 2;
}
break;
}
self.screenShotView.opaque = YES;
CGRect flutterBounds = self.view.bounds;
CGSize snapshotSize = CGSizeMake(flutterBounds.size.width ,
flutterBounds.size.height);
UIGraphicsBeginImageContextWithOptions(snapshotSize, NO, scale);
[self.view drawViewHierarchyInRect:flutterBounds
afterScreenUpdates:NO];
UIImage *snapImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return snapImage;
}
- (void)saveScreenShot
{
UIImage *snapImage = [self takeScreenShot];
if(snapImage){
FLBStackCacheObjectImg *cImg = [[FLBStackCacheObjectImg alloc] initWithImage:snapImage];
[[FLBStackCache sharedInstance] pushObject:cImg key:self.uniqueIDString];
}
}
- (void)clearCurrentScreenShotImage
{
self.screenShotView.image = nil;
}
- (UIImage *)getSavedScreenShot
{
FLBStackCacheObjectImg *cImg = [[FLBStackCache sharedInstance] objectForKey:self.uniqueIDString];
return [cImg image];
}
- (BOOL)isFlutterViewAttatched
{
return FLUTTER_VIEW.superview == self.view;
}
- (void)attatchFlutterView
- (void)attatchFlutterEngine
{
if([self isFlutterViewAttatched]) return;
[FLUTTER_VC willMoveToParentViewController:nil];
[FLUTTER_VC removeFromParentViewController];
[FLUTTER_VC didMoveToParentViewController:nil];
[FLUTTER_VC willMoveToParentViewController:self];
FLUTTER_VIEW.frame = self.view.bounds;
if(!self.screenShotView.image){
[self.view addSubview: FLUTTER_VIEW];
}else{
[self.view insertSubview:FLUTTER_VIEW belowSubview:self.screenShotView];
}
[self addChildViewController:FLUTTER_VC];
[FLUTTER_VC didMoveToParentViewController:self];
[FLUTTER_APP.flutterProvider prepareEngineIfNeeded];
[FLUTTER_APP.flutterProvider atacheToViewController:self];
}
- (BOOL)showSnapShotVew
- (void)detatchFlutterEngine
{
self.screenShotView.image = [self getSavedScreenShot];
if([self isFlutterViewAttatched]){
NSUInteger fIdx = [self.view.subviews indexOfObject:FLUTTER_VIEW];
NSUInteger sIdx = [self.view.subviews indexOfObject:self.screenShotView];
if(fIdx > sIdx){
[self.view insertSubview:FLUTTER_VIEW
atIndex:0];
}
}else{
}
return self.screenShotView.image != nil;
// [FLUTTER_APP.flutterProvider prepareEngineIfNeeded];
[FLUTTER_APP.flutterProvider detach];
}
- (void)showFlutterView
{
if(FLUTTER_VIEW.superview != self.view) return;
if([self isFlutterViewAttatched] ){
NSUInteger fIdx = [self.view.subviews indexOfObject:FLUTTER_VIEW];
NSUInteger sIdx = [self.view.subviews indexOfObject:self.screenShotView];
self.screenShotView.backgroundColor = UIColor.clearColor;
if(sIdx > fIdx){
[self.view insertSubview:self.screenShotView belowSubview:FLUTTER_VIEW];
[self flutterViewDidAppear:@{@"uid":self.uniqueIDString?:@""}];
}
}
[self clearCurrentScreenShotImage];
//Invalidate obsolete screenshot.
[FLBStackCache.sharedInstance invalidate:self.uniqueIDString];
}
#pragma mark - Life circle methods
......@@ -295,18 +179,17 @@ static NSUInteger kInstanceCounter = 0;
- (void)viewWillAppear:(BOOL)animated
{
if(self.navigationController.interactivePopGestureRecognizer.state == UIGestureRecognizerStateBegan){
self.interactiveGestureActive = true;
if([FLUTTER_APP contains:self]){
[self detatchFlutterEngine];
}else{
[self attatchFlutterEngine];
}
[[FLBFlutterApplication sharedApplication] resume];
[self surfaceUpdated:YES];
//For new page we should attach flutter view in view will appear
//for better performance.
if(![[FLBFlutterApplication sharedApplication] contains:self]){
[self attatchFlutterView];
}
[self showSnapShotVew];
[Service_NavigationService willShowPageContainer:^(NSNumber *result) {}
pageName:_name
......@@ -324,49 +207,21 @@ static NSUInteger kInstanceCounter = 0;
- (void)viewDidAppear:(BOOL)animated
{
[[FLBFlutterApplication sharedApplication] resume];
[FLUTTER_APP addUniqueViewController:self];
//Ensure flutter view is attached.
[self attatchFlutterView];
[self attatchFlutterEngine];
[self surfaceUpdated:YES];
[Service_NavigationService didShowPageContainer:^(NSNumber *result) {}
pageName:_name
params:_params
uniqueId:self.uniqueIDString];
[[FLBFlutterApplication sharedApplication] addUniqueViewController:self];
[super viewDidAppear:animated];
__weak typeof(self) weakSelf = self;
dispatch_after(dispatch_time(DISPATCH_TIME_NOW,
(int64_t)(2 * NSEC_PER_SEC)),
dispatch_get_main_queue(),^{
if (weakSelf.isViewLoaded && weakSelf.view.window) {
// viewController is visible
[weakSelf showFlutterView];
}
});
self.interactiveGestureActive = NO;
}
- (void)viewWillDisappear:(BOOL)animated
{
//is top.
if([FLUTTER_APP isTop:self.uniqueIDString]
&& self.navigationController.interactivePopGestureRecognizer.state != UIGestureRecognizerStateBegan
&& !self.interactiveGestureActive){
[self saveScreenShot];
}
self.interactiveGestureActive = NO;
self.screenShotView.image = [self getSavedScreenShot];
if(self.screenShotView.image){
[self.view bringSubviewToFront:self.screenShotView];
}
[Service_NavigationService willDisappearPageContainer:^(NSNumber *result) {}
pageName:_name
params:_params
......@@ -377,16 +232,12 @@ static NSUInteger kInstanceCounter = 0;
- (void)viewDidDisappear:(BOOL)animated
{
[self detatchFlutterEngine];
[Service_NavigationService didDisappearPageContainer:^(NSNumber *result) {}
pageName:_name
params:_params
uniqueId:self.uniqueIDString];
[self clearCurrentScreenShotImage];
[super viewDidDisappear:animated];
[FLUTTER_APP inactive];
self.interactiveGestureActive = NO;
}
#pragma mark - FLBViewControllerResultHandler
......
/*
* The MIT License (MIT)
*
* Copyright (c) 2019 Alibaba Group
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#import <Foundation/Foundation.h>
@class FLBStackCache;
@protocol FLBStackCacheObject<NSObject>
@required
@property (nonatomic,copy) NSString *key;
- (BOOL)writeToFileWithKey:(NSString *)key
queue:(dispatch_queue_t)queue
cache:(FLBStackCache *)cache
completion:(void (^)(NSError *err,NSString *path))completion;
+ (BOOL)loadFromFileWithKey:(NSString *)key
queue:(dispatch_queue_t)queue
cache:(FLBStackCache *)cache
completion:(void (^)(NSError *err ,id<FLBStackCacheObject>))completion;
- (BOOL)removeCachedFileWithKey:(NSString *)key
queue:(dispatch_queue_t)queue
cache:(FLBStackCache *)cache
completion:(void (^)(NSError *, NSString *))completion;
@end
@interface FLBStackCache : NSObject
+ (instancetype)sharedInstance;
/**
* Num of objects allowed in memory.
* Default value is set to 2.
*/
@property (nonatomic,assign) NSUInteger inMemoryCount;
#pragma mark - basic operations.
- (void)pushObject:(id<FLBStackCacheObject>)obj key:(NSString *)key;
- (id<FLBStackCacheObject>)remove:(NSString *)key;
- (void)invalidate:(NSString *)key;
- (BOOL)empty;
- (void)clear;
- (id<FLBStackCacheObject>)objectForKey:(NSString *)key;
#pragma mark - Disk thing.
- (NSString *)cacheDir;
@end
/*
* The MIT License (MIT)
*
* Copyright (c) 2019 Alibaba Group
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#import "FLBStackCache.h"
@interface FLBStackCache()
@property (nonatomic,strong) NSMutableArray *keyStack;
@property (nonatomic,strong) NSMutableDictionary *typesMap;
@property (nonatomic,strong) NSMutableDictionary *inMemoryObjectsMap;
@property (nonatomic,strong) NSMutableDictionary *loadinMap;
@property (nonatomic,strong) dispatch_queue_t queueIO;
@end
@implementation FLBStackCache
+ (instancetype)sharedInstance
{
static id sInstance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sInstance = [self.class new];
});
return sInstance;
}
- (BOOL)empty
{
return _keyStack.count<=0;
}
- (void)clear
{
[self.keyStack removeAllObjects];
[self.inMemoryObjectsMap removeAllObjects];
[self.typesMap removeAllObjects];
NSError *err = nil;
[[NSFileManager defaultManager] removeItemAtPath:self.cacheDir error:&err];
if (err) {
NSLog(@"fail to remove cache dir %@",err);
}
}
- (instancetype)init
{
if (self = [super init]) {
_keyStack = [NSMutableArray new];
_inMemoryObjectsMap = [NSMutableDictionary new];
_loadinMap = [NSMutableDictionary new];
_typesMap = [NSMutableDictionary new];
_queueIO = dispatch_queue_create("Stack cache working queue", NULL);
}
_inMemoryCount = 2;
return self;
}
- (void)pushObject:(id<FLBStackCacheObject>)obj
key:(NSString *)key
{
if (!obj || key.length <= 0) {
return;
}
if(![_keyStack containsObject:key]){
[_keyStack addObject:key];
}else{
//return;
}
obj.key = key;
_typesMap[key] = obj.class;
_inMemoryObjectsMap[key] = obj;
for(NSUInteger i = _keyStack.count - _inMemoryObjectsMap.count ;
i < _keyStack.count && _inMemoryObjectsMap.count > _inMemoryCount;
i++){
NSString *keyToSave = _keyStack[i];
if(_inMemoryObjectsMap[keyToSave]){
id<FLBStackCacheObject> ob = _inMemoryObjectsMap[keyToSave];
[_inMemoryObjectsMap removeObjectForKey:keyToSave];
[ob writeToFileWithKey:keyToSave
queue:_queueIO
cache:self
completion:^(NSError *err, NSString *path) {
if (err) {
NSLog(@"Caching object to file failed!");
}
}];
}
}
}
- (id<FLBStackCacheObject>)objectForKey:(NSString *)key
{
return _inMemoryObjectsMap[key];
}
- (id<FLBStackCacheObject>)remove:(NSString *)key
{
if([self empty]) return nil;
if(![_keyStack containsObject:key]) return nil;
id ob = _inMemoryObjectsMap[key];
[_keyStack removeObject:key];
[_inMemoryObjectsMap removeObjectForKey:key];
[_typesMap removeObjectForKey:key];
[self preloadIfNeeded];
return ob;
}
- (void)invalidate:(NSString *)key
{
if(!key || [self empty]) return;
if(![_keyStack containsObject:key]) return;
id<FLBStackCacheObject> ob = _inMemoryObjectsMap[key];
[ob removeCachedFileWithKey:key
queue:_queueIO
cache:self
completion:^(NSError *err, NSString *k) {
}];
[_inMemoryObjectsMap removeObjectForKey:key];
[self preloadIfNeeded];
}
- (void)preloadIfNeeded
{
for(NSString *key in self.keyStack.reverseObjectEnumerator){
Class typeClass = _typesMap[key];
id cache = _inMemoryObjectsMap[key];
if(typeClass && !cache && [typeClass conformsToProtocol: @protocol(FLBStackCacheObject)]){
_loadinMap[key] = @(YES);
[typeClass loadFromFileWithKey:key
queue:_queueIO
cache:self
completion:^(NSError *err ,id<FLBStackCacheObject> ob){
[self.loadinMap removeObjectForKey:key];
if (ob && !err) {
if(self.typesMap[key]){
self.inMemoryObjectsMap[key] = ob;
}
}else{
NSLog(@"preload object from file failed!");
}
}];
}
if(_inMemoryObjectsMap.count + _loadinMap.count >= _inMemoryCount){
break;
}
}
}
- (NSString *)cacheDir
{
static NSString *cachePath = nil;
if (!cachePath) {
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
NSString *cacheDirectory = [paths objectAtIndex:0];
cachePath = [cacheDirectory stringByAppendingPathComponent:@"FlutterScreenshots"];
}
BOOL dir = NO;
if(![[NSFileManager defaultManager] fileExistsAtPath:cachePath isDirectory:&dir]){
NSError *eror = nil;
[[NSFileManager defaultManager] createDirectoryAtPath:cachePath
withIntermediateDirectories:YES
attributes:nil
error:&eror];
if (eror) {
NSLog(@"%@",eror);
}
}
return cachePath;
}
@end
/*
* The MIT License (MIT)
*
* Copyright (c) 2019 Alibaba Group
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#import <Foundation/Foundation.h>
#import "FLBStackCache.h"
@interface FLBStackCacheObjectImg : NSObject<FLBStackCacheObject>
@property (nonatomic,copy) NSString *key;
- (instancetype)initWithImage:(UIImage *)image;
- (UIImage *)image;
@end
/*
* The MIT License (MIT)
*
* Copyright (c) 2019 Alibaba Group
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#import "FLBStackCacheObjectImg.h"
@interface FLBStackCacheObjectImg()
@property (nonatomic,strong) UIImage *image;
@end
@implementation FLBStackCacheObjectImg
- (instancetype)initWithImage:(UIImage *)image
{
if (self = [super init]) {
_image = image;
}
return self;
}
+ (BOOL)loadFromFileWithKey:(NSString *)key
queue:(dispatch_queue_t)queue
cache:(FLBStackCache *)cache
completion:(void (^)(NSError *, id<FLBStackCacheObject>))completion
{
dispatch_async(queue, ^{
UIImage *image = [[UIImage alloc] initWithContentsOfFile:[self filePathByKey:key dirPath:cache.cacheDir]];
if (completion) {
if (image) {
FLBStackCacheObjectImg *ob = [[FLBStackCacheObjectImg alloc] initWithImage:image];
ob.key = key;
completion(nil,ob);
}else{
completion([NSError new],nil);
}
}
});
return YES;
}
+ (NSString *)filePathByKey:(NSString *)key dirPath:(NSString *)cacheDir
{
key = [key stringByReplacingOccurrencesOfString:@"/" withString:@""];
key = [key stringByReplacingOccurrencesOfString:@":" withString:@""];
NSString *path = [cacheDir stringByAppendingPathComponent:key];
return path;
}
- (BOOL)writeToFileWithKey:(NSString *)key
queue:(dispatch_queue_t)queue
cache:(FLBStackCache *)cache
completion:(void (^)(NSError *, NSString *))completion
{
if(!_image){
return NO;
}
dispatch_async(queue, ^{
NSData *imgData = UIImagePNGRepresentation(self.image);
NSString *filePath = [FLBStackCacheObjectImg filePathByKey:key dirPath:cache.cacheDir];
[imgData writeToFile:filePath atomically:YES];
if (completion) {
completion(nil,key);
}
});
return YES;
}
- (BOOL)removeCachedFileWithKey:(NSString *)key
queue:(dispatch_queue_t)queue
cache:(FLBStackCache *)cache
completion:(void (^)(NSError *, NSString *))completion
{
if(!key){
return NO;
}
dispatch_async(queue, ^{
NSString *filePath = [FLBStackCacheObjectImg filePathByKey:key dirPath:cache.cacheDir];
NSError *err = nil;
[NSFileManager.defaultManager removeItemAtPath:filePath error:&err];
if (completion) {
completion(err,key);
}
});
return YES;
}
@end
/*
* The MIT License (MIT)
*
* Copyright (c) 2019 Alibaba Group
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#import <Foundation/Foundation.h>
#define kFLBMemoryInspectorChangedNotification @"__FlutterMemoryInspectorChangedNotification__"
#define kFLBMemoryInspectorKeyCondition @"condition"
typedef NS_ENUM(NSUInteger,FLBMemoryCondition) {
FLBMemoryConditionUnknown,
FLBMemoryConditionNormal,
FLBMemoryConditionLowMemory,
FLBMemoryConditionExtremelyLow,
FLBMemoryConditionAboutToDie
};
@interface FLBMemoryInspector : NSObject
+ (instancetype)sharedInstance;
- (FLBMemoryCondition)currentCondition;
- (int64_t)currentFootPrint;
- (int64_t)deviceMemory;
- (BOOL)smallMemoryDevice;
@end
/*
* The MIT License (MIT)
*
* Copyright (c) 2019 Alibaba Group
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#import "FLBMemoryInspector.h"
#include <mach/mach.h>
#include <stdlib.h>
#include <sys/sysctl.h>
#define MB(_v_) (_v_*1024*1024)
#define SYSTEM_VERSION_EQUAL_TO(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedSame)
#define SYSTEM_VERSION_GREATER_THAN(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedDescending)
#define SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedAscending)
#define SYSTEM_VERSION_LESS_THAN(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedAscending)
#define SYSTEM_VERSION_LESS_THAN_OR_EQUAL_TO(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedDescending)
@interface FLBMemoryInspector()
@property(nonatomic,assign) FLBMemoryCondition condition;
@end
@implementation FLBMemoryInspector
+ (instancetype)sharedInstance
{
static id sInstance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sInstance = [[self.class alloc] init];
});
return sInstance;
}
static bool isHighterThanIos9(){
bool ret = SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"9.0.0");
return ret;
}
static int64_t memoryFootprint()
{
task_vm_info_data_t vmInfo;
mach_msg_type_number_t count = TASK_VM_INFO_COUNT;
kern_return_t result = task_info(mach_task_self(), TASK_VM_INFO, (task_info_t) &vmInfo, &count);
if (result != KERN_SUCCESS)
return -1;
return vmInfo.phys_footprint;
}
static int64_t _memoryWarningLimit()
{
size_t size;
sysctlbyname("hw.machine", NULL, &size, NULL, 0);
char *machine =(char *) malloc(size);
sysctlbyname("hw.machine", machine, &size, NULL, 0);
NSString *platform = [NSString stringWithUTF8String:machine];
free(machine);
if ([platform isEqualToString:@"iPhone5,1"]) return MB(600);
if ([platform isEqualToString:@"iPhone5,2"]) return MB(600);
if ([platform isEqualToString:@"iPhone5,3"]) return MB(600);
if ([platform isEqualToString:@"iPhone5,4"]) return MB(600);
if ([platform isEqualToString:@"iPhone6,1"]) return MB(600);
if ([platform isEqualToString:@"iPhone6,2"]) return MB(600);
if ([platform isEqualToString:@"iPhone7,1"]) return MB(600);
if ([platform isEqualToString:@"iPhone7,2"]) return MB(600);
if ([platform isEqualToString:@"iPhone8,1"]) return MB(1280);
if ([platform isEqualToString:@"iPhone8,2"]) return MB(1280);
if ([platform isEqualToString:@"iPhone8,4"]) return MB(1280);
if ([platform isEqualToString:@"iPhone9,1"]) return MB(1280);
if ([platform isEqualToString:@"iPhone9,2"]) return MB(1950);
if ([platform isEqualToString:@"iPhone9,3"]) return MB(1280);
if ([platform isEqualToString:@"iPhone9,4"]) return MB(1950);
if ([platform isEqualToString:@"iPhone10,1"]) return MB(1280);
if ([platform isEqualToString:@"iPhone10,2"]) return MB(1950);
if ([platform isEqualToString:@"iPhone10,3"]) return MB(1950);
if ([platform isEqualToString:@"iPhone10,4"]) return MB(1280);
if ([platform isEqualToString:@"iPhone10,5"]) return MB(1950);
if ([platform isEqualToString:@"iPhone10,6"]) return MB(1950);
return 0;
}
static int64_t getLimit(){
const static size_t l = _memoryWarningLimit();
return l;
}
- (int64_t)deviceMemory
{
int64_t size = [NSProcessInfo processInfo].physicalMemory;
return size;
}
- (BOOL)smallMemoryDevice
{
if([self deviceMemory] <= MB(1024)){
return YES;
}else{
return NO;
}
}
- (FLBMemoryCondition)currentCondition
{
FLBMemoryCondition newCondition = FLBMemoryConditionUnknown;
if(!isHighterThanIos9() || getLimit() <= 0){
newCondition = FLBMemoryConditionUnknown;
}else if(memoryFootprint() < getLimit() * 0.40){
newCondition = FLBMemoryConditionNormal;
}else if(memoryFootprint() < getLimit() * 0.60){
newCondition = FLBMemoryConditionLowMemory;
}else if(memoryFootprint() < getLimit() * 0.80){
newCondition = FLBMemoryConditionExtremelyLow;
}else{
newCondition = FLBMemoryConditionAboutToDie;
}
if (newCondition != self.condition) {
[[NSNotificationCenter defaultCenter] postNotificationName:kFLBMemoryInspectorChangedNotification
object:@{kFLBMemoryInspectorKeyCondition:@(newCondition)}];
}
self.condition = newCondition;
return newCondition;
}
- (int64_t)currentFootPrint
{
return memoryFootprint();
}
@end
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment