From 8c5ace47a7e4d7d47361bf878ba05c3890618ae5 Mon Sep 17 00:00:00 2001 From: Michael Goderbauer Date: Wed, 6 Jan 2021 10:55:56 -0800 Subject: [PATCH 01/15] almost compiles --- .../ios/framework/Headers/FlutterEngine.h | 35 ++++++- .../Headers/FlutterHeadlessDartRunner.h | 22 ++++- .../framework/Source/FlutterAppDelegate.mm | 31 ++++++ .../ios/framework/Source/FlutterEngine.mm | 25 +++++ .../framework/Source/FlutterEngine_Internal.h | 2 + .../Source/FlutterHeadlessDartRunner.mm | 16 ++- .../Source/FlutterRestorationPlugin.h | 23 +++++ .../Source/FlutterRestorationPlugin.mm | 98 +++++++++++++++++++ .../framework/Source/FlutterViewController.mm | 27 ++++- 9 files changed, 275 insertions(+), 4 deletions(-) create mode 100644 shell/platform/darwin/ios/framework/Source/FlutterRestorationPlugin.h create mode 100644 shell/platform/darwin/ios/framework/Source/FlutterRestorationPlugin.mm diff --git a/shell/platform/darwin/ios/framework/Headers/FlutterEngine.h b/shell/platform/darwin/ios/framework/Headers/FlutterEngine.h index 3067410f96a97..1b3a4522912bd 100644 --- a/shell/platform/darwin/ios/framework/Headers/FlutterEngine.h +++ b/shell/platform/darwin/ios/framework/Headers/FlutterEngine.h @@ -135,7 +135,30 @@ FLUTTER_EXPORT */ - (instancetype)initWithName:(NSString*)labelPrefix project:(nullable FlutterDartProject*)project - allowHeadlessExecution:(BOOL)allowHeadlessExecution NS_DESIGNATED_INITIALIZER; + allowHeadlessExecution:(BOOL)allowHeadlessExecution; + +/** + * Initialize this FlutterEngine with a `FlutterDartProject`. + * + * If the FlutterDartProject is not specified, the FlutterEngine will attempt to locate + * the project in a default location (the flutter_assets folder in the iOS application + * bundle). + * + * A newly initialized engine will not run the `FlutterDartProject` until either + * `-runWithEntrypoint:` or `-runWithEntrypoint:libraryURI:` is called. + * + * @param labelPrefix The label prefix used to identify threads for this instance. Should + * be unique across FlutterEngine instances, and is used in instrumentation to label + * the threads used by this FlutterEngine. + * @param project The `FlutterDartProject` to run. + * @param allowHeadlessExecution Whether or not to allow this instance to continue + * running after passing a nil `FlutterViewController` to `-setViewController:`. + * @param waitForRestorationData TODO + */ +- (instancetype)initWithName:(NSString*)labelPrefix + project:(nullable FlutterDartProject*)project + allowHeadlessExecution:(BOOL)allowHeadlessExecution + restorationEnabled:(BOOL)restorationEnabled NS_DESIGNATED_INITIALIZER; + (instancetype)new NS_UNAVAILABLE; @@ -273,6 +296,16 @@ FLUTTER_EXPORT */ @property(nonatomic, readonly) FlutterMethodChannel* navigationChannel; +/** + * The `FlutterMethodChannel` used for restoration related platform messages. + * + * Can be nil after `destroyContext` is called. + * + * @see [Navigation + * Channel](https://docs.flutter.io/flutter/services/SystemChannels/restoration-constant.html) + */ +@property(nonatomic, readonly) FlutterMethodChannel* restorationChannel; + /** * The `FlutterMethodChannel` used for core platform messages, such as * information about the screen orientation. diff --git a/shell/platform/darwin/ios/framework/Headers/FlutterHeadlessDartRunner.h b/shell/platform/darwin/ios/framework/Headers/FlutterHeadlessDartRunner.h index 40bc84d82706b..d46110d4d725f 100644 --- a/shell/platform/darwin/ios/framework/Headers/FlutterHeadlessDartRunner.h +++ b/shell/platform/darwin/ios/framework/Headers/FlutterHeadlessDartRunner.h @@ -64,7 +64,27 @@ FLUTTER_DEPRECATED("FlutterEngine should be used rather than FlutterHeadlessDart */ - (instancetype)initWithName:(NSString*)labelPrefix project:(FlutterDartProject*)projectOrNil - allowHeadlessExecution:(BOOL)allowHeadlessExecution NS_DESIGNATED_INITIALIZER; + allowHeadlessExecution:(BOOL)allowHeadlessExecution; + +/** + * Iniitalize this FlutterHeadlessDartRunner with a `FlutterDartProject`. + * + * If the FlutterDartProject is not specified, the FlutterHeadlessDartRunner will attempt to locate + * the project in a default location. + * + * A newly initialized engine will not run the `FlutterDartProject` until either + * `-runWithEntrypoint:` or `-runWithEntrypoint:libraryURI` is called. + * + * @param labelPrefix The label prefix used to identify threads for this instance. Should + * be unique across FlutterEngine instances + * @param projectOrNil The `FlutterDartProject` to run. + * @param allowHeadlessExecution Must be set to `YES`. + * @param restorationEnabled TODO + */ +- (instancetype)initWithName:(NSString*)labelPrefix + project:(FlutterDartProject*)projectOrNil + allowHeadlessExecution:(BOOL)allowHeadlessExecution + restorationEnabled:(BOOL)restorationEnabled NS_DESIGNATED_INITIALIZER; /** * Not recommended for use - will initialize with a default label ("io.flutter.headless") diff --git a/shell/platform/darwin/ios/framework/Source/FlutterAppDelegate.mm b/shell/platform/darwin/ios/framework/Source/FlutterAppDelegate.mm index 1e574aec6343d..e56c9b7e6f4f6 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterAppDelegate.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterAppDelegate.mm @@ -4,6 +4,8 @@ #import "flutter/shell/platform/darwin/ios/framework/Headers/FlutterAppDelegate.h" +#include + #import "flutter/fml/logging.h" #import "flutter/shell/platform/darwin/ios/framework/Headers/FlutterPluginAppLifeCycleDelegate.h" #import "flutter/shell/platform/darwin/ios/framework/Headers/FlutterViewController.h" @@ -24,6 +26,7 @@ @implementation FlutterAppDelegate { } - (instancetype)init { + NSLog(@"MIKE: HELLOO"); if (self = [super init]) { _lifeCycleDelegate = [[FlutterPluginAppLifeCycleDelegate alloc] init]; } @@ -307,5 +310,33 @@ - (void)logCapabilityConfigurationWarningIfNeeded:(SEL)selector { } } } + +#pragma mark - State Restoration +- (BOOL)application:(UIApplication *)application shouldSaveApplicationState:(NSCoder *)coder { + [coder encodeInt64: self.lastAppModificationTime forKey:@"mod-date"]; + return YES; +} + +- (BOOL)application:(UIApplication *)application shouldRestoreApplicationState:(NSCoder *)coder { + int64_t stateDate = [coder decodeInt64ForKey:@"mod-date"]; + return self.lastAppModificationTime == stateDate; +} + +- (BOOL)application:(UIApplication *)application shouldSaveSecureApplicationState:(NSCoder *)coder { + [coder encodeInt64: self.lastAppModificationTime forKey:@"mod-date"]; + return YES; +} + +- (BOOL)application:(UIApplication *)application shouldRestoreSecureApplicationState:(NSCoder *)coder { + int64_t stateDate = [coder decodeInt64ForKey:@"mod-date"]; + return self.lastAppModificationTime == stateDate; +} + +- (int64_t)lastAppModificationTime { + NSDate *fileDate; + [[[NSBundle mainBundle] executableURL] getResourceValue:&fileDate forKey:NSURLContentModificationDateKey error:nil]; + return [fileDate timeIntervalSince1970]; +} + @end diff --git a/shell/platform/darwin/ios/framework/Source/FlutterEngine.mm b/shell/platform/darwin/ios/framework/Source/FlutterEngine.mm index 9c4a259e02c96..2e1b94d40a920 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterEngine.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterEngine.mm @@ -71,8 +71,10 @@ @implementation FlutterEngine { // Channels fml::scoped_nsobject _platformPlugin; fml::scoped_nsobject _textInputPlugin; + fml::scoped_nsobject _restorationPlugin; fml::scoped_nsobject _localizationChannel; fml::scoped_nsobject _navigationChannel; + fml::scoped_nsobject _restorationChannel; fml::scoped_nsobject _platformChannel; fml::scoped_nsobject _platformViewsChannel; fml::scoped_nsobject _textInputChannel; @@ -84,6 +86,7 @@ @implementation FlutterEngine { int64_t _nextTextureId; BOOL _allowHeadlessExecution; + BOOL _restorationEnabled; FlutterBinaryMessengerRelay* _binaryMessenger; std::unique_ptr _connections; } @@ -103,10 +106,18 @@ - (instancetype)initWithName:(NSString*)labelPrefix project:(FlutterDartProject* - (instancetype)initWithName:(NSString*)labelPrefix project:(FlutterDartProject*)project allowHeadlessExecution:(BOOL)allowHeadlessExecution { + return [self initWithName:labelPrefix project:project allowHeadlessExecution:allowHeadlessExecution restorationEnabled:NO]; +} + +- (instancetype)initWithName:(NSString*)labelPrefix + project:(FlutterDartProject*)project + allowHeadlessExecution:(BOOL)allowHeadlessExecution + restorationEnabled:(BOOL)restorationEnabled { self = [super init]; NSAssert(self, @"Super init cannot be nil"); NSAssert(labelPrefix, @"labelPrefix is required"); + _restorationEnabled = restorationEnabled; _allowHeadlessExecution = allowHeadlessExecution; _labelPrefix = [labelPrefix copy]; @@ -331,12 +342,18 @@ - (FlutterPlatformPlugin*)platformPlugin { - (FlutterTextInputPlugin*)textInputPlugin { return _textInputPlugin.get(); } +- (FlutterRestorationPlugin*)restorationPlugin { + return _restorationPlugin.get(); +} - (FlutterMethodChannel*)localizationChannel { return _localizationChannel.get(); } - (FlutterMethodChannel*)navigationChannel { return _navigationChannel.get(); } +- (FlutterMethodChannel*)restorationChannel { + return _restorationChannel.get(); +} - (FlutterMethodChannel*)platformChannel { return _platformChannel.get(); } @@ -363,6 +380,7 @@ - (NSURL*)observatoryUrl { - (void)resetChannels { _localizationChannel.reset(); _navigationChannel.reset(); + _restorationChannel.reset(); _platformChannel.reset(); _platformViewsChannel.reset(); _textInputChannel.reset(); @@ -413,6 +431,11 @@ - (void)setupChannels { _initialRoute = nil; } + _restorationChannel.reset([[FlutterMethodChannel alloc] + initWithName:@"flutter/restoration" + binaryMessenger:self.binaryMessenger + codec:[FlutterStandardMethodCodec sharedInstance]]); + _platformChannel.reset([[FlutterMethodChannel alloc] initWithName:@"flutter/platform" binaryMessenger:self.binaryMessenger @@ -452,6 +475,8 @@ - (void)setupChannels { _textInputPlugin.get().textInputDelegate = self; _platformPlugin.reset([[FlutterPlatformPlugin alloc] initWithEngine:[self getWeakPtr]]); + + _restorationPlugin.reset([[FlutterRestorationPlugin alloc] initWithChannel:_restorationChannel.get() restorationEnabled:_restorationEnabled]); } - (void)maybeSetupPlatformViewChannels { diff --git a/shell/platform/darwin/ios/framework/Source/FlutterEngine_Internal.h b/shell/platform/darwin/ios/framework/Source/FlutterEngine_Internal.h index 36c3b2c433834..698e5fdf8df2a 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterEngine_Internal.h +++ b/shell/platform/darwin/ios/framework/Source/FlutterEngine_Internal.h @@ -18,6 +18,7 @@ #import "flutter/shell/platform/darwin/ios/framework/Source/FlutterDartProject_Internal.h" #import "flutter/shell/platform/darwin/ios/framework/Source/FlutterPlatformPlugin.h" #import "flutter/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h" +#import "flutter/shell/platform/darwin/ios/framework/Source/FlutterRestorationPlugin.h" #import "flutter/shell/platform/darwin/ios/framework/Source/FlutterTextInputDelegate.h" #import "flutter/shell/platform/darwin/ios/framework/Source/FlutterTextInputPlugin.h" #import "flutter/shell/platform/darwin/ios/platform_view_ios.h" @@ -42,6 +43,7 @@ extern NSString* const FlutterEngineWillDealloc; - (FlutterPlatformPlugin*)platformPlugin; - (std::shared_ptr&)platformViewsController; - (FlutterTextInputPlugin*)textInputPlugin; +- (FlutterRestorationPlugin*)restorationPlugin; - (void)launchEngine:(NSString*)entrypoint libraryURI:(NSString*)libraryOrNil; - (BOOL)createShell:(NSString*)entrypoint libraryURI:(NSString*)libraryOrNil diff --git a/shell/platform/darwin/ios/framework/Source/FlutterHeadlessDartRunner.mm b/shell/platform/darwin/ios/framework/Source/FlutterHeadlessDartRunner.mm index 71c62522a7c30..8247fb01c4402 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterHeadlessDartRunner.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterHeadlessDartRunner.mm @@ -35,10 +35,24 @@ - (instancetype)initWithName:(NSString*)labelPrefix allowHeadlessExecution:(BOOL)allowHeadlessExecution { NSAssert(allowHeadlessExecution == YES, @"Cannot initialize a FlutterHeadlessDartRunner without headless execution."); + return [self initWithName:labelPrefix + project:projectOrNil + allowHeadlessExecution:allowHeadlessExecution + restorationEnabled:NO]; +} + +- (instancetype)initWithName:(NSString*)labelPrefix + project:(FlutterDartProject*)projectOrNil + allowHeadlessExecution:(BOOL)allowHeadlessExecution + restorationEnabled:(BOOL)restorationEnabled{ + NSAssert(allowHeadlessExecution == YES, + @"Cannot initialize a FlutterHeadlessDartRunner without headless execution."); return [super initWithName:labelPrefix project:projectOrNil - allowHeadlessExecution:allowHeadlessExecution]; + allowHeadlessExecution:allowHeadlessExecution + restorationEnabled:restorationEnabled]; } + - (instancetype)init { return [self initWithName:@"io.flutter.headless" project:nil]; } diff --git a/shell/platform/darwin/ios/framework/Source/FlutterRestorationPlugin.h b/shell/platform/darwin/ios/framework/Source/FlutterRestorationPlugin.h new file mode 100644 index 0000000000000..516d2d49dd96e --- /dev/null +++ b/shell/platform/darwin/ios/framework/Source/FlutterRestorationPlugin.h @@ -0,0 +1,23 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef SHELL_PLATFORM_IOS_FRAMEWORK_SOURCE_FLUTTERRESTORATIONPLUGIN_H_ +#define SHELL_PLATFORM_IOS_FRAMEWORK_SOURCE_FLUTTERRESTORATIONPLUGIN_H_ + +#import + +#include "flutter/fml/memory/weak_ptr.h" +#import "flutter/shell/platform/darwin/common/framework/Headers/FlutterChannels.h" + +@interface FlutterRestorationPlugin : NSObject + +- (instancetype)init NS_UNAVAILABLE; ++ (instancetype)new NS_UNAVAILABLE; +- (instancetype)initWithChannel:(fml::WeakPtr)channel restorationEnabled:(BOOL)waitForData NS_DESIGNATED_INITIALIZER; + +- (NSData*)restorationData; +- (void)restorationData:(NSData *)data; +- (void)restorationComplete; +@end +#endif // SHELL_PLATFORM_IOS_FRAMEWORK_SOURCE_FLUTTERRESTORATIONPLUGIN_H_ diff --git a/shell/platform/darwin/ios/framework/Source/FlutterRestorationPlugin.mm b/shell/platform/darwin/ios/framework/Source/FlutterRestorationPlugin.mm new file mode 100644 index 0000000000000..767f8e6a07de6 --- /dev/null +++ b/shell/platform/darwin/ios/framework/Source/FlutterRestorationPlugin.mm @@ -0,0 +1,98 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "flutter/shell/platform/darwin/ios/framework/Source/FlutterRestorationPlugin.h" + +#import +#import + +#include "flutter/fml/logging.h" + + +@implementation FlutterRestorationPlugin { + BOOL _waitForData; + BOOL _restorationEnabled; + FlutterResult _pendingRequest; + NSData* _restorationData; +} + +- (instancetype)init { + @throw([NSException exceptionWithName:@"FlutterRestorationPlugin must initWithEngine" + reason:nil + userInfo:nil]); + /Users/goderbauer/dev/engine/src/flutter/shell/platform/darwin/ios/framework/Source/FlutterRestorationPlugin.h +} + +- (instancetype)initWithChannel:(fml::WeakPtr)channel restorationEnabled:(BOOL)restorationEnabled { + FML_DCHECK(channel) << "channel must be set"; + self = [super init]; + if (self) { + [channel.get() setMethodCallHandler:^(FlutterMethodCall* call, FlutterResult result) { + [self handleMethodCall:call result:result]; + }]; + _restorationEnabled = restorationEnabled; + _waitForData = restorationEnabled; + } + return self; +} + +- (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result { + if ([[call method] isEqualToString:@"put"]) { + FlutterStandardTypedData* data = [call arguments]; + NSData* newData = [[data data] retain]; + if (_restorationData != nil) { + [_restorationData release]; + } + _restorationData = newData; + result(nil); + } else if ([[call method] isEqualToString:@"get"]) { + if (!_restorationEnabled || !_waitForData) { + result( [self dataForFramework] ); + return; + } + _pendingRequest = [result retain]; + } else { + result(FlutterMethodNotImplemented); + } +} + +_ (NSData*)restorationData { + return _restorationData; +} + +- (void)restorationData:(NSData*)data { + NSData* newData = [data retain]; + if (_restorationData != nil) { + [_restorationData release]; + } + _restorationData = newData; + if (_pendingRequest != nil) { + _pendingRequest( [self dataForFramework] ); + [_pendingRequest release]; + _pendingRequest = nil; + _waitForData = NO; + } +} + +- (void)restorationComplete { + _waitForData = NO; + if (_pendingRequest != nil) { + NSAssert(_restorationEnabled, @"No request can be pending when restoration is disabled."); + _pendingRequest( [self dataForFramework] ); + [_pendingRequest release]; + _pendingRequest = nil; + } +} + +- (NSDictionary*)dataForFramework { + if (!_restorationEnabled) { + return @{ @"enabled": @NO }; + } + if (_restorationData == nil) { + return @{ @"enabled": @YES }; + } + return @{@"enabled": @YES, @"data": [FlutterStandardTypedData typedDataWithBytes:_restorationData]}; +} + +@end diff --git a/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm b/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm index a0cffaace53b3..a09629f804e9a 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm @@ -112,6 +112,7 @@ @implementation FlutterViewController { - (instancetype)initWithEngine:(FlutterEngine*)engine nibName:(nullable NSString*)nibName bundle:(nullable NSBundle*)nibBundle { + NSLog(@"FlutterViewController: 1"); NSAssert(engine != nil, @"Engine is required"); self = [super initWithNibName:nibName bundle:nibBundle]; if (self) { @@ -140,6 +141,7 @@ - (instancetype)initWithEngine:(FlutterEngine*)engine - (instancetype)initWithProject:(FlutterDartProject*)project nibName:(NSString*)nibName bundle:(NSBundle*)nibBundle { + NSLog(@"FlutterViewController: 2"); self = [super initWithNibName:nibName bundle:nibBundle]; if (self) { [self sharedSetupWithProject:project initialRoute:nil]; @@ -152,6 +154,7 @@ - (instancetype)initWithProject:(FlutterDartProject*)project initialRoute:(NSString*)initialRoute nibName:(NSString*)nibName bundle:(NSBundle*)nibBundle { + NSLog(@"FlutterViewController: 3"); self = [super initWithNibName:nibName bundle:nibBundle]; if (self) { [self sharedSetupWithProject:project initialRoute:initialRoute]; @@ -161,11 +164,14 @@ - (instancetype)initWithProject:(FlutterDartProject*)project } - (instancetype)initWithNibName:(NSString*)nibNameOrNil bundle:(NSBundle*)nibBundleOrNil { + NSLog(@"FlutterViewController: 4"); return [self initWithProject:nil nibName:nil bundle:nil]; } - (instancetype)initWithCoder:(NSCoder*)aDecoder { + NSLog(@"FlutterViewController: 5"); self = [super initWithCoder:aDecoder]; + NSLog(@">> Restoration Identifier: %@", [self restorationIdentifier]); return self; } @@ -177,6 +183,7 @@ - (void)awakeFromNib { } - (instancetype)init { + NSLog(@"FlutterViewController: 6"); return [self initWithProject:nil nibName:nil bundle:nil]; } @@ -188,10 +195,12 @@ - (void)sharedSetupWithProject:(nullable FlutterDartProject*)project project = [[[FlutterDartProject alloc] init] autorelease]; } FlutterView.forceSoftwareRendering = project.settings.enable_software_rendering; + NSLog(@">> NEW ENGINE"); auto engine = fml::scoped_nsobject{[[FlutterEngine alloc] initWithName:@"io.flutter" project:project - allowHeadlessExecution:self.engineAllowHeadlessExecution]}; + allowHeadlessExecution:self.engineAllowHeadlessExecution + restorationEnabled:[self restorationIdentifier] != nil]}; if (!engine) { return; @@ -618,6 +627,7 @@ - (void)surfaceUpdated:(BOOL)appeared { #pragma mark - UIViewController lifecycle notifications - (void)viewDidLoad { + NSLog(@">>>> viewDidLoad"); TRACE_EVENT0("flutter", "viewDidLoad"); if (_engine && _engineNeedsLaunch) { @@ -644,6 +654,7 @@ - (void)viewDidLoad { - (void)viewWillAppear:(BOOL)animated { TRACE_EVENT0("flutter", "viewWillAppear"); + NSLog(@">>>> viewWillAppear"); // Send platform settings to Flutter, e.g., platform brightness. [self onUserSettingsChanged:nil]; @@ -654,6 +665,7 @@ - (void)viewWillAppear:(BOOL)animated { [self surfaceUpdated:YES]; } [[_engine.get() lifecycleChannel] sendMessage:@"AppLifecycleState.inactive"]; + [[_engine.get() restorationPlugin] restorationComplete]; [super viewWillAppear:animated]; } @@ -1521,6 +1533,19 @@ - (void)scrollEvent:(UIPanGestureRecognizer*)recognizer API_AVAILABLE(ios(13.4)) packet->SetPointerData(/*index=*/0, pointer_data); [_engine.get() dispatchPointerDataPacket:std::move(packet)]; + +#pragma mark - State Restoration + +- (void)encodeRestorableStateWithCoder:(NSCoder *)coder { + NSLog(@"FlutterViewController: encodeRestorableStateWithCoder"); + NSData* restorationData = [[_engine.get() restorationPlugin] restorationData]; + [coder encodeDataObject:restorationData]; +} + +- (void)decodeRestorableStateWithCoder:(NSCoder *)coder { + NSLog(@"FlutterViewController: decodeRestorableStateWithCoder"); + NSData* restorationData = [coder decodeDataObject]; + [[_engine.get() restorationPlugin] restorationData:restorationData]; } @end From fb1272becfc5a0fab5a2878affbce54a87dda8d1 Mon Sep 17 00:00:00 2001 From: Michael Goderbauer Date: Wed, 6 Jan 2021 16:29:38 -0800 Subject: [PATCH 02/15] it works --- shell/platform/darwin/ios/BUILD.gn | 2 ++ .../ios/framework/Source/FlutterRestorationPlugin.h | 2 +- .../ios/framework/Source/FlutterRestorationPlugin.mm | 9 ++++----- .../darwin/ios/framework/Source/FlutterViewController.mm | 4 ++-- 4 files changed, 9 insertions(+), 8 deletions(-) diff --git a/shell/platform/darwin/ios/BUILD.gn b/shell/platform/darwin/ios/BUILD.gn index e516886474113..2e7c9fbaaf0e8 100644 --- a/shell/platform/darwin/ios/BUILD.gn +++ b/shell/platform/darwin/ios/BUILD.gn @@ -66,6 +66,8 @@ source_set("flutter_framework_source") { "framework/Source/FlutterPlatformViews_Internal.h", "framework/Source/FlutterPlatformViews_Internal.mm", "framework/Source/FlutterPluginAppLifeCycleDelegate.mm", + "framework/Source/FlutterRestorationPlugin.h", + "framework/Source/FlutterRestorationPlugin.mm", "framework/Source/FlutterTextInputDelegate.h", "framework/Source/FlutterTextInputPlugin.h", "framework/Source/FlutterTextInputPlugin.mm", diff --git a/shell/platform/darwin/ios/framework/Source/FlutterRestorationPlugin.h b/shell/platform/darwin/ios/framework/Source/FlutterRestorationPlugin.h index 516d2d49dd96e..533e2860d9900 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterRestorationPlugin.h +++ b/shell/platform/darwin/ios/framework/Source/FlutterRestorationPlugin.h @@ -14,7 +14,7 @@ - (instancetype)init NS_UNAVAILABLE; + (instancetype)new NS_UNAVAILABLE; -- (instancetype)initWithChannel:(fml::WeakPtr)channel restorationEnabled:(BOOL)waitForData NS_DESIGNATED_INITIALIZER; +- (instancetype)initWithChannel:(FlutterMethodChannel*)channel restorationEnabled:(BOOL)waitForData NS_DESIGNATED_INITIALIZER; - (NSData*)restorationData; - (void)restorationData:(NSData *)data; diff --git a/shell/platform/darwin/ios/framework/Source/FlutterRestorationPlugin.mm b/shell/platform/darwin/ios/framework/Source/FlutterRestorationPlugin.mm index 767f8e6a07de6..dd5e088425fbf 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterRestorationPlugin.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterRestorationPlugin.mm @@ -18,17 +18,16 @@ @implementation FlutterRestorationPlugin { } - (instancetype)init { - @throw([NSException exceptionWithName:@"FlutterRestorationPlugin must initWithEngine" + @throw([NSException exceptionWithName:@"FlutterRestorationPlugin must initWithChannel:restorationEnabled:" reason:nil userInfo:nil]); - /Users/goderbauer/dev/engine/src/flutter/shell/platform/darwin/ios/framework/Source/FlutterRestorationPlugin.h } -- (instancetype)initWithChannel:(fml::WeakPtr)channel restorationEnabled:(BOOL)restorationEnabled { +- (instancetype)initWithChannel:(FlutterMethodChannel*)channel restorationEnabled:(BOOL)restorationEnabled { FML_DCHECK(channel) << "channel must be set"; self = [super init]; if (self) { - [channel.get() setMethodCallHandler:^(FlutterMethodCall* call, FlutterResult result) { + [channel setMethodCallHandler:^(FlutterMethodCall* call, FlutterResult result) { [self handleMethodCall:call result:result]; }]; _restorationEnabled = restorationEnabled; @@ -57,7 +56,7 @@ - (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result { } } -_ (NSData*)restorationData { +- (NSData*)restorationData { return _restorationData; } diff --git a/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm b/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm index a09629f804e9a..c0bbdce9111d0 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm @@ -1537,14 +1537,14 @@ - (void)scrollEvent:(UIPanGestureRecognizer*)recognizer API_AVAILABLE(ios(13.4)) #pragma mark - State Restoration - (void)encodeRestorableStateWithCoder:(NSCoder *)coder { - NSLog(@"FlutterViewController: encodeRestorableStateWithCoder"); NSData* restorationData = [[_engine.get() restorationPlugin] restorationData]; + NSLog(@"FlutterViewController: encodeRestorableStateWithCoder %@", restorationData); [coder encodeDataObject:restorationData]; } - (void)decodeRestorableStateWithCoder:(NSCoder *)coder { - NSLog(@"FlutterViewController: decodeRestorableStateWithCoder"); NSData* restorationData = [coder decodeDataObject]; + NSLog(@"FlutterViewController: decodeRestorableStateWithCoder %@", restorationData); [[_engine.get() restorationPlugin] restorationData:restorationData]; } From 4901439b179ec3d7891400ca89cb356c98efe512 Mon Sep 17 00:00:00 2001 From: Michael Goderbauer Date: Wed, 6 Jan 2021 17:42:09 -0800 Subject: [PATCH 03/15] Reset on hot restart --- .../ios/framework/Source/FlutterRestorationPlugin.h | 2 +- .../ios/framework/Source/FlutterRestorationPlugin.mm | 11 +++++++++++ .../ios/framework/Source/FlutterViewController.mm | 4 ++++ .../framework/Source/FlutterViewController_Internal.h | 2 ++ shell/platform/darwin/ios/platform_view_ios.mm | 1 + 5 files changed, 19 insertions(+), 1 deletion(-) diff --git a/shell/platform/darwin/ios/framework/Source/FlutterRestorationPlugin.h b/shell/platform/darwin/ios/framework/Source/FlutterRestorationPlugin.h index 533e2860d9900..8f84aeea57a47 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterRestorationPlugin.h +++ b/shell/platform/darwin/ios/framework/Source/FlutterRestorationPlugin.h @@ -11,7 +11,6 @@ #import "flutter/shell/platform/darwin/common/framework/Headers/FlutterChannels.h" @interface FlutterRestorationPlugin : NSObject - - (instancetype)init NS_UNAVAILABLE; + (instancetype)new NS_UNAVAILABLE; - (instancetype)initWithChannel:(FlutterMethodChannel*)channel restorationEnabled:(BOOL)waitForData NS_DESIGNATED_INITIALIZER; @@ -19,5 +18,6 @@ - (NSData*)restorationData; - (void)restorationData:(NSData *)data; - (void)restorationComplete; +- (void)reset; @end #endif // SHELL_PLATFORM_IOS_FRAMEWORK_SOURCE_FLUTTERRESTORATIONPLUGIN_H_ diff --git a/shell/platform/darwin/ios/framework/Source/FlutterRestorationPlugin.mm b/shell/platform/darwin/ios/framework/Source/FlutterRestorationPlugin.mm index dd5e088425fbf..a74caf40b46be 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterRestorationPlugin.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterRestorationPlugin.mm @@ -84,6 +84,17 @@ - (void)restorationComplete { } } +- (void)reset { + if (_restorationData != nil) { + [_restorationData release]; + } + _restorationData = nil; + if (_pendingRequest != nil) { + [_pendingRequest release]; + } + _pendingRequest = nil; +} + - (NSDictionary*)dataForFramework { if (!_restorationEnabled) { return @{ @"enabled": @NO }; diff --git a/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm b/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm index c0bbdce9111d0..5adc6834e7e71 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm @@ -1548,4 +1548,8 @@ - (void)decodeRestorableStateWithCoder:(NSCoder *)coder { [[_engine.get() restorationPlugin] restorationData:restorationData]; } +- (FlutterRestorationPlugin*)restorationPlugin { + return [_engine.get() restorationPlugin]; +} + @end diff --git a/shell/platform/darwin/ios/framework/Source/FlutterViewController_Internal.h b/shell/platform/darwin/ios/framework/Source/FlutterViewController_Internal.h index 93584f237b4f0..f51a88df1b1cf 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterViewController_Internal.h +++ b/shell/platform/darwin/ios/framework/Source/FlutterViewController_Internal.h @@ -8,6 +8,7 @@ #include "flutter/fml/memory/weak_ptr.h" #import "flutter/shell/platform/darwin/ios/framework/Headers/FlutterViewController.h" +#import "flutter/shell/platform/darwin/ios/framework/Source/FlutterRestorationPlugin.h" namespace flutter { class FlutterPlatformViewsController; @@ -27,6 +28,7 @@ extern NSNotificationName const FlutterViewControllerShowHomeIndicator; @property(nonatomic, readonly) BOOL isPresentingViewController; - (fml::WeakPtr)getWeakPtr; - (std::shared_ptr&)platformViewsController; +- (FlutterRestorationPlugin*)restorationPlugin; @end diff --git a/shell/platform/darwin/ios/platform_view_ios.mm b/shell/platform/darwin/ios/platform_view_ios.mm index 1b48773517bc2..6dfb00ddd546d 100644 --- a/shell/platform/darwin/ios/platform_view_ios.mm +++ b/shell/platform/darwin/ios/platform_view_ios.mm @@ -207,6 +207,7 @@ return; } [owner_controller_.get() platformViewsController]->Reset(); + [[owner_controller_.get() restorationPlugin] reset]; } std::unique_ptr> PlatformViewIOS::ComputePlatformResolvedLocales( From 6b8fac98b8e9c6853a88c32d0163290711d2ea12 Mon Sep 17 00:00:00 2001 From: Michael Goderbauer Date: Thu, 7 Jan 2021 11:46:37 -0800 Subject: [PATCH 04/15] tests --- shell/platform/darwin/ios/BUILD.gn | 1 + .../Source/FlutterRestorationPlugin.mm | 2 +- .../Source/FlutterRestorationPluginTest.mm | 191 ++++++++++++++++++ 3 files changed, 193 insertions(+), 1 deletion(-) create mode 100644 shell/platform/darwin/ios/framework/Source/FlutterRestorationPluginTest.mm diff --git a/shell/platform/darwin/ios/BUILD.gn b/shell/platform/darwin/ios/BUILD.gn index 2e7c9fbaaf0e8..dafb1dce0ed92 100644 --- a/shell/platform/darwin/ios/BUILD.gn +++ b/shell/platform/darwin/ios/BUILD.gn @@ -223,6 +223,7 @@ shared_library("ios_test_flutter") { "framework/Source/FlutterEngineGroupTest.mm", "framework/Source/FlutterEngineTest.mm", "framework/Source/FlutterPluginAppLifeCycleDelegateTest.m", + "framework/Source/FlutterRestorationPluginTest.mm", "framework/Source/FlutterTextInputPluginTest.m", "framework/Source/FlutterViewControllerTest.mm", "framework/Source/SemanticsObjectTest.mm", diff --git a/shell/platform/darwin/ios/framework/Source/FlutterRestorationPlugin.mm b/shell/platform/darwin/ios/framework/Source/FlutterRestorationPlugin.mm index a74caf40b46be..f9f73f37b1015 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterRestorationPlugin.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterRestorationPlugin.mm @@ -66,11 +66,11 @@ - (void)restorationData:(NSData*)data { [_restorationData release]; } _restorationData = newData; + _waitForData = NO; if (_pendingRequest != nil) { _pendingRequest( [self dataForFramework] ); [_pendingRequest release]; _pendingRequest = nil; - _waitForData = NO; } } diff --git a/shell/platform/darwin/ios/framework/Source/FlutterRestorationPluginTest.mm b/shell/platform/darwin/ios/framework/Source/FlutterRestorationPluginTest.mm new file mode 100644 index 0000000000000..42e253ae80137 --- /dev/null +++ b/shell/platform/darwin/ios/framework/Source/FlutterRestorationPluginTest.mm @@ -0,0 +1,191 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "flutter/shell/platform/darwin/ios/framework/Source/FlutterRestorationPlugin.h" + +#import +#import + +#import "flutter/shell/platform/darwin/common/framework/Headers/FlutterMacros.h" +#import "flutter/shell/platform/darwin/common/framework/Headers/FlutterChannels.h" + + +FLUTTER_ASSERT_ARC + +@interface FlutterRestorationPlugin () +- (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result; +@end + +@interface FlutterRestorationPluginTest : XCTestCase +@end + +@implementation FlutterRestorationPluginTest { + id restorationChannel; +} + +- (void)setUp { + [super setUp]; + restorationChannel = OCMClassMock([FlutterMethodChannel class]); +} + +- (void)tearDown { + [restorationChannel stopMocking]; + + [super tearDown]; +} + +#pragma mark - Tests + +- (void)testRestorationEnabledWaitsForData { + FlutterRestorationPlugin* restorationPlugin = [[FlutterRestorationPlugin alloc] initWithChannel: restorationChannel restorationEnabled: YES]; + + FlutterMethodCall* methodCall =[FlutterMethodCall methodCallWithMethodName:@"get" + arguments:nil]; + __block id capturedResult; + [restorationPlugin handleMethodCall:methodCall + result:^(id _Nullable result){ + capturedResult = result; + }]; + XCTAssertNil(capturedResult); + + NSData* data = [@"testrestortiondata" dataUsingEncoding:NSUTF8StringEncoding]; + [restorationPlugin restorationData: data]; + XCTAssertEqual([capturedResult count], 2u); + XCTAssertEqual([capturedResult objectForKey: @"enabled"], @YES); + XCTAssertEqual([[capturedResult objectForKey: @"data"] data], data); +} + +- (void)testRestorationDisabledRespondsRightAway { + FlutterRestorationPlugin* restorationPlugin = [[FlutterRestorationPlugin alloc] initWithChannel: restorationChannel restorationEnabled: NO]; + + FlutterMethodCall* methodCall =[FlutterMethodCall methodCallWithMethodName:@"get" + arguments:nil]; + __block id capturedResult; + [restorationPlugin handleMethodCall:methodCall + result:^(id _Nullable result){ + capturedResult = result; + }]; + XCTAssertEqual([capturedResult count], 1u); + XCTAssertEqual([capturedResult objectForKey: @"enabled"], @NO); +} + +- (void)testRespondsRightAwayWhenDataIsSet { + FlutterRestorationPlugin* restorationPlugin = [[FlutterRestorationPlugin alloc] initWithChannel: restorationChannel restorationEnabled: YES]; + + NSData* data = [@"testrestortiondata" dataUsingEncoding:NSUTF8StringEncoding]; + [restorationPlugin restorationData: data]; + + __block id capturedResult; + FlutterMethodCall* methodCall =[FlutterMethodCall methodCallWithMethodName:@"get" + arguments:nil]; + [restorationPlugin handleMethodCall:methodCall + result:^(id _Nullable result){ + capturedResult = result; + }]; + XCTAssertEqual([capturedResult count], 2u); + XCTAssertEqual([capturedResult objectForKey: @"enabled"], @YES); + XCTAssertEqual([[capturedResult objectForKey: @"data"] data], data); +} + +- (void)testRespondsWithNoDataWhenRestorationIsCompletedWithoutData { + FlutterRestorationPlugin* restorationPlugin = [[FlutterRestorationPlugin alloc] initWithChannel: restorationChannel restorationEnabled: YES]; + + FlutterMethodCall* methodCall =[FlutterMethodCall methodCallWithMethodName:@"get" + arguments:nil]; + __block id capturedResult; + [restorationPlugin handleMethodCall:methodCall + result:^(id _Nullable result){ + capturedResult = result; + }]; + XCTAssertNil(capturedResult); + + [restorationPlugin restorationComplete]; + XCTAssertEqual([capturedResult count], 1u); + XCTAssertEqual([capturedResult objectForKey: @"enabled"], @YES); +} + +- (void)testRespondsRightAwayWithNoDataWhenRestorationIsCompleted { + FlutterRestorationPlugin* restorationPlugin = [[FlutterRestorationPlugin alloc] initWithChannel: restorationChannel restorationEnabled: YES]; + + [restorationPlugin restorationComplete]; + + __block id capturedResult; + FlutterMethodCall* methodCall =[FlutterMethodCall methodCallWithMethodName:@"get" + arguments:nil]; + [restorationPlugin handleMethodCall:methodCall + result:^(id _Nullable result){ + capturedResult = result; + }]; + XCTAssertEqual([capturedResult count], 1u); + XCTAssertEqual([capturedResult objectForKey: @"enabled"], @YES); +} + +- (void)testReturnsDataSetByFramework { + FlutterRestorationPlugin* restorationPlugin = [[FlutterRestorationPlugin alloc] initWithChannel: restorationChannel restorationEnabled: YES]; + [restorationPlugin restorationComplete]; + + NSData* data = [@"testrestortiondata" dataUsingEncoding:NSUTF8StringEncoding]; + FlutterMethodCall* methodCall =[FlutterMethodCall methodCallWithMethodName:@"put" + arguments:[FlutterStandardTypedData typedDataWithBytes:data]]; + [restorationPlugin handleMethodCall:methodCall + result:^(id _Nullable result){ + XCTAssertNil(result); + }]; + XCTAssertEqual([restorationPlugin restorationData], data); +} + +- (void)testRespondsWithDataSetByFramework { + FlutterRestorationPlugin* restorationPlugin = [[FlutterRestorationPlugin alloc] initWithChannel: restorationChannel restorationEnabled: YES]; + [restorationPlugin restorationComplete]; + + NSData* data = [@"testrestortiondata" dataUsingEncoding:NSUTF8StringEncoding]; + FlutterMethodCall* methodCall =[FlutterMethodCall methodCallWithMethodName:@"put" + arguments:[FlutterStandardTypedData typedDataWithBytes:data]]; + [restorationPlugin handleMethodCall:methodCall + result:^(id _Nullable result){ + XCTAssertNil(result); + }]; + XCTAssertEqual([restorationPlugin restorationData], data); + + __block id capturedResult; + methodCall = [FlutterMethodCall methodCallWithMethodName:@"get" + arguments:nil]; + [restorationPlugin handleMethodCall:methodCall + result:^(id _Nullable result){ + capturedResult = result; + }]; + XCTAssertEqual([capturedResult count], 2u); + XCTAssertEqual([capturedResult objectForKey: @"enabled"], @YES); + XCTAssertEqual([[capturedResult objectForKey: @"data"] data], data); +} + +- (void)testResetClearsData { + FlutterRestorationPlugin* restorationPlugin = [[FlutterRestorationPlugin alloc] initWithChannel: restorationChannel restorationEnabled: YES]; + [restorationPlugin restorationComplete]; + + NSData* data = [@"testrestortiondata" dataUsingEncoding:NSUTF8StringEncoding]; + FlutterMethodCall* methodCall =[FlutterMethodCall methodCallWithMethodName:@"put" + arguments:[FlutterStandardTypedData typedDataWithBytes:data]]; + [restorationPlugin handleMethodCall:methodCall + result:^(id _Nullable result){ + XCTAssertNil(result); + }]; + XCTAssertEqual([restorationPlugin restorationData], data); + + [restorationPlugin reset]; + XCTAssertNil([restorationPlugin restorationData]); + + + __block id capturedResult; + methodCall = [FlutterMethodCall methodCallWithMethodName:@"get" + arguments:nil]; + [restorationPlugin handleMethodCall:methodCall + result:^(id _Nullable result){ + capturedResult = result; + }]; + XCTAssertEqual([capturedResult count], 1u); + XCTAssertEqual([capturedResult objectForKey: @"enabled"], @YES); +} + +@end From 0fa6966cd0e3e76f383f103549f8ca9e5fbdbdd4 Mon Sep 17 00:00:00 2001 From: Michael Goderbauer Date: Thu, 7 Jan 2021 11:57:53 -0800 Subject: [PATCH 05/15] cleanup --- .../darwin/ios/framework/Headers/FlutterEngine.h | 4 ++-- .../framework/Headers/FlutterHeadlessDartRunner.h | 2 +- .../ios/framework/Source/FlutterAppDelegate.mm | 1 - .../ios/framework/Source/FlutterViewController.mm | 12 ------------ 4 files changed, 3 insertions(+), 16 deletions(-) diff --git a/shell/platform/darwin/ios/framework/Headers/FlutterEngine.h b/shell/platform/darwin/ios/framework/Headers/FlutterEngine.h index 1b3a4522912bd..b91a725d7ed85 100644 --- a/shell/platform/darwin/ios/framework/Headers/FlutterEngine.h +++ b/shell/platform/darwin/ios/framework/Headers/FlutterEngine.h @@ -153,7 +153,7 @@ FLUTTER_EXPORT * @param project The `FlutterDartProject` to run. * @param allowHeadlessExecution Whether or not to allow this instance to continue * running after passing a nil `FlutterViewController` to `-setViewController:`. - * @param waitForRestorationData TODO + * @param restorationEnabled Whether state restoration is enabled. When true, the framework will wait for the attached view controller to provide restoration data. */ - (instancetype)initWithName:(NSString*)labelPrefix project:(nullable FlutterDartProject*)project @@ -301,7 +301,7 @@ FLUTTER_EXPORT * * Can be nil after `destroyContext` is called. * - * @see [Navigation + * @see [Restoration * Channel](https://docs.flutter.io/flutter/services/SystemChannels/restoration-constant.html) */ @property(nonatomic, readonly) FlutterMethodChannel* restorationChannel; diff --git a/shell/platform/darwin/ios/framework/Headers/FlutterHeadlessDartRunner.h b/shell/platform/darwin/ios/framework/Headers/FlutterHeadlessDartRunner.h index d46110d4d725f..418f10e404818 100644 --- a/shell/platform/darwin/ios/framework/Headers/FlutterHeadlessDartRunner.h +++ b/shell/platform/darwin/ios/framework/Headers/FlutterHeadlessDartRunner.h @@ -79,7 +79,7 @@ FLUTTER_DEPRECATED("FlutterEngine should be used rather than FlutterHeadlessDart * be unique across FlutterEngine instances * @param projectOrNil The `FlutterDartProject` to run. * @param allowHeadlessExecution Must be set to `YES`. - * @param restorationEnabled TODO + * @param restorationEnabled Must be set to `NO`. */ - (instancetype)initWithName:(NSString*)labelPrefix project:(FlutterDartProject*)projectOrNil diff --git a/shell/platform/darwin/ios/framework/Source/FlutterAppDelegate.mm b/shell/platform/darwin/ios/framework/Source/FlutterAppDelegate.mm index e56c9b7e6f4f6..c92883e5197c2 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterAppDelegate.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterAppDelegate.mm @@ -26,7 +26,6 @@ @implementation FlutterAppDelegate { } - (instancetype)init { - NSLog(@"MIKE: HELLOO"); if (self = [super init]) { _lifeCycleDelegate = [[FlutterPluginAppLifeCycleDelegate alloc] init]; } diff --git a/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm b/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm index 5adc6834e7e71..039dda3d85b94 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm @@ -112,7 +112,6 @@ @implementation FlutterViewController { - (instancetype)initWithEngine:(FlutterEngine*)engine nibName:(nullable NSString*)nibName bundle:(nullable NSBundle*)nibBundle { - NSLog(@"FlutterViewController: 1"); NSAssert(engine != nil, @"Engine is required"); self = [super initWithNibName:nibName bundle:nibBundle]; if (self) { @@ -141,7 +140,6 @@ - (instancetype)initWithEngine:(FlutterEngine*)engine - (instancetype)initWithProject:(FlutterDartProject*)project nibName:(NSString*)nibName bundle:(NSBundle*)nibBundle { - NSLog(@"FlutterViewController: 2"); self = [super initWithNibName:nibName bundle:nibBundle]; if (self) { [self sharedSetupWithProject:project initialRoute:nil]; @@ -154,7 +152,6 @@ - (instancetype)initWithProject:(FlutterDartProject*)project initialRoute:(NSString*)initialRoute nibName:(NSString*)nibName bundle:(NSBundle*)nibBundle { - NSLog(@"FlutterViewController: 3"); self = [super initWithNibName:nibName bundle:nibBundle]; if (self) { [self sharedSetupWithProject:project initialRoute:initialRoute]; @@ -164,14 +161,11 @@ - (instancetype)initWithProject:(FlutterDartProject*)project } - (instancetype)initWithNibName:(NSString*)nibNameOrNil bundle:(NSBundle*)nibBundleOrNil { - NSLog(@"FlutterViewController: 4"); return [self initWithProject:nil nibName:nil bundle:nil]; } - (instancetype)initWithCoder:(NSCoder*)aDecoder { - NSLog(@"FlutterViewController: 5"); self = [super initWithCoder:aDecoder]; - NSLog(@">> Restoration Identifier: %@", [self restorationIdentifier]); return self; } @@ -183,7 +177,6 @@ - (void)awakeFromNib { } - (instancetype)init { - NSLog(@"FlutterViewController: 6"); return [self initWithProject:nil nibName:nil bundle:nil]; } @@ -195,7 +188,6 @@ - (void)sharedSetupWithProject:(nullable FlutterDartProject*)project project = [[[FlutterDartProject alloc] init] autorelease]; } FlutterView.forceSoftwareRendering = project.settings.enable_software_rendering; - NSLog(@">> NEW ENGINE"); auto engine = fml::scoped_nsobject{[[FlutterEngine alloc] initWithName:@"io.flutter" project:project @@ -627,7 +619,6 @@ - (void)surfaceUpdated:(BOOL)appeared { #pragma mark - UIViewController lifecycle notifications - (void)viewDidLoad { - NSLog(@">>>> viewDidLoad"); TRACE_EVENT0("flutter", "viewDidLoad"); if (_engine && _engineNeedsLaunch) { @@ -654,7 +645,6 @@ - (void)viewDidLoad { - (void)viewWillAppear:(BOOL)animated { TRACE_EVENT0("flutter", "viewWillAppear"); - NSLog(@">>>> viewWillAppear"); // Send platform settings to Flutter, e.g., platform brightness. [self onUserSettingsChanged:nil]; @@ -1538,13 +1528,11 @@ - (void)scrollEvent:(UIPanGestureRecognizer*)recognizer API_AVAILABLE(ios(13.4)) - (void)encodeRestorableStateWithCoder:(NSCoder *)coder { NSData* restorationData = [[_engine.get() restorationPlugin] restorationData]; - NSLog(@"FlutterViewController: encodeRestorableStateWithCoder %@", restorationData); [coder encodeDataObject:restorationData]; } - (void)decodeRestorableStateWithCoder:(NSCoder *)coder { NSData* restorationData = [coder decodeDataObject]; - NSLog(@"FlutterViewController: decodeRestorableStateWithCoder %@", restorationData); [[_engine.get() restorationPlugin] restorationData:restorationData]; } From b12df56e9f063d5cbdaf49bf194e96204c53cba3 Mon Sep 17 00:00:00 2001 From: Michael Goderbauer Date: Thu, 7 Jan 2021 12:07:35 -0800 Subject: [PATCH 06/15] licenses --- ci/licenses_golden/licenses_flutter | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ci/licenses_golden/licenses_flutter b/ci/licenses_golden/licenses_flutter index 31c79959f78d8..c8e0baf0286ff 100755 --- a/ci/licenses_golden/licenses_flutter +++ b/ci/licenses_golden/licenses_flutter @@ -993,6 +993,9 @@ FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterPlatfor FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterPluginAppLifeCycleDelegate.mm FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterPluginAppLifeCycleDelegateTest.m FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterPluginAppLifeCycleDelegate_internal.h +FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterRestorationPlugin.h +FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterRestorationPlugin.mm +FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterRestorationPluginTest.mm FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterTextInputDelegate.h FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterTextInputPlugin.h FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterTextInputPlugin.mm From 4f1676abe0d2b6fa918d7ab05551385ce79fcbb1 Mon Sep 17 00:00:00 2001 From: Michael Goderbauer Date: Thu, 7 Jan 2021 12:14:24 -0800 Subject: [PATCH 07/15] format --- .../framework/Source/FlutterAppDelegate.mm | 29 ++-- .../ios/framework/Source/FlutterEngine.mm | 13 +- .../Source/FlutterHeadlessDartRunner.mm | 2 +- .../Source/FlutterRestorationPlugin.h | 5 +- .../Source/FlutterRestorationPlugin.mm | 26 ++-- .../Source/FlutterRestorationPluginTest.mm | 144 +++++++++--------- .../framework/Source/FlutterViewController.mm | 4 +- 7 files changed, 119 insertions(+), 104 deletions(-) diff --git a/shell/platform/darwin/ios/framework/Source/FlutterAppDelegate.mm b/shell/platform/darwin/ios/framework/Source/FlutterAppDelegate.mm index c92883e5197c2..49f59c7b62456 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterAppDelegate.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterAppDelegate.mm @@ -309,33 +309,36 @@ - (void)logCapabilityConfigurationWarningIfNeeded:(SEL)selector { } } } - + #pragma mark - State Restoration -- (BOOL)application:(UIApplication *)application shouldSaveApplicationState:(NSCoder *)coder { - [coder encodeInt64: self.lastAppModificationTime forKey:@"mod-date"]; +- (BOOL)application:(UIApplication*)application shouldSaveApplicationState:(NSCoder*)coder { + [coder encodeInt64:self.lastAppModificationTime forKey:@"mod-date"]; return YES; } - -- (BOOL)application:(UIApplication *)application shouldRestoreApplicationState:(NSCoder *)coder { + +- (BOOL)application:(UIApplication*)application shouldRestoreApplicationState:(NSCoder*)coder { int64_t stateDate = [coder decodeInt64ForKey:@"mod-date"]; return self.lastAppModificationTime == stateDate; } - -- (BOOL)application:(UIApplication *)application shouldSaveSecureApplicationState:(NSCoder *)coder { - [coder encodeInt64: self.lastAppModificationTime forKey:@"mod-date"]; + +- (BOOL)application:(UIApplication*)application shouldSaveSecureApplicationState:(NSCoder*)coder { + [coder encodeInt64:self.lastAppModificationTime forKey:@"mod-date"]; return YES; } -- (BOOL)application:(UIApplication *)application shouldRestoreSecureApplicationState:(NSCoder *)coder { +- (BOOL)application:(UIApplication*)application + shouldRestoreSecureApplicationState:(NSCoder*)coder { int64_t stateDate = [coder decodeInt64ForKey:@"mod-date"]; return self.lastAppModificationTime == stateDate; } - + - (int64_t)lastAppModificationTime { - NSDate *fileDate; - [[[NSBundle mainBundle] executableURL] getResourceValue:&fileDate forKey:NSURLContentModificationDateKey error:nil]; + NSDate* fileDate; + [[[NSBundle mainBundle] executableURL] getResourceValue:&fileDate + forKey:NSURLContentModificationDateKey + error:nil]; return [fileDate timeIntervalSince1970]; } - + @end diff --git a/shell/platform/darwin/ios/framework/Source/FlutterEngine.mm b/shell/platform/darwin/ios/framework/Source/FlutterEngine.mm index 2e1b94d40a920..ccad2bb7f7582 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterEngine.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterEngine.mm @@ -106,7 +106,10 @@ - (instancetype)initWithName:(NSString*)labelPrefix project:(FlutterDartProject* - (instancetype)initWithName:(NSString*)labelPrefix project:(FlutterDartProject*)project allowHeadlessExecution:(BOOL)allowHeadlessExecution { - return [self initWithName:labelPrefix project:project allowHeadlessExecution:allowHeadlessExecution restorationEnabled:NO]; + return [self initWithName:labelPrefix + project:project + allowHeadlessExecution:allowHeadlessExecution + restorationEnabled:NO]; } - (instancetype)initWithName:(NSString*)labelPrefix @@ -435,7 +438,7 @@ - (void)setupChannels { initWithName:@"flutter/restoration" binaryMessenger:self.binaryMessenger codec:[FlutterStandardMethodCodec sharedInstance]]); - + _platformChannel.reset([[FlutterMethodChannel alloc] initWithName:@"flutter/platform" binaryMessenger:self.binaryMessenger @@ -475,8 +478,10 @@ - (void)setupChannels { _textInputPlugin.get().textInputDelegate = self; _platformPlugin.reset([[FlutterPlatformPlugin alloc] initWithEngine:[self getWeakPtr]]); - - _restorationPlugin.reset([[FlutterRestorationPlugin alloc] initWithChannel:_restorationChannel.get() restorationEnabled:_restorationEnabled]); + + _restorationPlugin.reset([[FlutterRestorationPlugin alloc] + initWithChannel:_restorationChannel.get() + restorationEnabled:_restorationEnabled]); } - (void)maybeSetupPlatformViewChannels { diff --git a/shell/platform/darwin/ios/framework/Source/FlutterHeadlessDartRunner.mm b/shell/platform/darwin/ios/framework/Source/FlutterHeadlessDartRunner.mm index 8247fb01c4402..2f3dcc28774fa 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterHeadlessDartRunner.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterHeadlessDartRunner.mm @@ -44,7 +44,7 @@ - (instancetype)initWithName:(NSString*)labelPrefix - (instancetype)initWithName:(NSString*)labelPrefix project:(FlutterDartProject*)projectOrNil allowHeadlessExecution:(BOOL)allowHeadlessExecution - restorationEnabled:(BOOL)restorationEnabled{ + restorationEnabled:(BOOL)restorationEnabled { NSAssert(allowHeadlessExecution == YES, @"Cannot initialize a FlutterHeadlessDartRunner without headless execution."); return [super initWithName:labelPrefix diff --git a/shell/platform/darwin/ios/framework/Source/FlutterRestorationPlugin.h b/shell/platform/darwin/ios/framework/Source/FlutterRestorationPlugin.h index 8f84aeea57a47..7fdc9d42fc42c 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterRestorationPlugin.h +++ b/shell/platform/darwin/ios/framework/Source/FlutterRestorationPlugin.h @@ -13,10 +13,11 @@ @interface FlutterRestorationPlugin : NSObject - (instancetype)init NS_UNAVAILABLE; + (instancetype)new NS_UNAVAILABLE; -- (instancetype)initWithChannel:(FlutterMethodChannel*)channel restorationEnabled:(BOOL)waitForData NS_DESIGNATED_INITIALIZER; +- (instancetype)initWithChannel:(FlutterMethodChannel*)channel + restorationEnabled:(BOOL)waitForData NS_DESIGNATED_INITIALIZER; - (NSData*)restorationData; -- (void)restorationData:(NSData *)data; +- (void)restorationData:(NSData*)data; - (void)restorationComplete; - (void)reset; @end diff --git a/shell/platform/darwin/ios/framework/Source/FlutterRestorationPlugin.mm b/shell/platform/darwin/ios/framework/Source/FlutterRestorationPlugin.mm index f9f73f37b1015..c8ec4b37243d4 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterRestorationPlugin.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterRestorationPlugin.mm @@ -9,7 +9,6 @@ #include "flutter/fml/logging.h" - @implementation FlutterRestorationPlugin { BOOL _waitForData; BOOL _restorationEnabled; @@ -18,12 +17,14 @@ @implementation FlutterRestorationPlugin { } - (instancetype)init { - @throw([NSException exceptionWithName:@"FlutterRestorationPlugin must initWithChannel:restorationEnabled:" - reason:nil - userInfo:nil]); + @throw([NSException + exceptionWithName:@"FlutterRestorationPlugin must initWithChannel:restorationEnabled:" + reason:nil + userInfo:nil]); } -- (instancetype)initWithChannel:(FlutterMethodChannel*)channel restorationEnabled:(BOOL)restorationEnabled { +- (instancetype)initWithChannel:(FlutterMethodChannel*)channel + restorationEnabled:(BOOL)restorationEnabled { FML_DCHECK(channel) << "channel must be set"; self = [super init]; if (self) { @@ -47,7 +48,7 @@ - (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result { result(nil); } else if ([[call method] isEqualToString:@"get"]) { if (!_restorationEnabled || !_waitForData) { - result( [self dataForFramework] ); + result([self dataForFramework]); return; } _pendingRequest = [result retain]; @@ -68,7 +69,7 @@ - (void)restorationData:(NSData*)data { _restorationData = newData; _waitForData = NO; if (_pendingRequest != nil) { - _pendingRequest( [self dataForFramework] ); + _pendingRequest([self dataForFramework]); [_pendingRequest release]; _pendingRequest = nil; } @@ -78,7 +79,7 @@ - (void)restorationComplete { _waitForData = NO; if (_pendingRequest != nil) { NSAssert(_restorationEnabled, @"No request can be pending when restoration is disabled."); - _pendingRequest( [self dataForFramework] ); + _pendingRequest([self dataForFramework]); [_pendingRequest release]; _pendingRequest = nil; } @@ -97,12 +98,15 @@ - (void)reset { - (NSDictionary*)dataForFramework { if (!_restorationEnabled) { - return @{ @"enabled": @NO }; + return @{@"enabled" : @NO}; } if (_restorationData == nil) { - return @{ @"enabled": @YES }; + return @{@"enabled" : @YES}; } - return @{@"enabled": @YES, @"data": [FlutterStandardTypedData typedDataWithBytes:_restorationData]}; + return @{ + @"enabled" : @YES, + @"data" : [FlutterStandardTypedData typedDataWithBytes:_restorationData] + }; } @end diff --git a/shell/platform/darwin/ios/framework/Source/FlutterRestorationPluginTest.mm b/shell/platform/darwin/ios/framework/Source/FlutterRestorationPluginTest.mm index 42e253ae80137..11d6f0324730a 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterRestorationPluginTest.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterRestorationPluginTest.mm @@ -7,9 +7,8 @@ #import #import -#import "flutter/shell/platform/darwin/common/framework/Headers/FlutterMacros.h" #import "flutter/shell/platform/darwin/common/framework/Headers/FlutterChannels.h" - +#import "flutter/shell/platform/darwin/common/framework/Headers/FlutterMacros.h" FLUTTER_ASSERT_ARC @@ -38,154 +37,157 @@ - (void)tearDown { #pragma mark - Tests - (void)testRestorationEnabledWaitsForData { - FlutterRestorationPlugin* restorationPlugin = [[FlutterRestorationPlugin alloc] initWithChannel: restorationChannel restorationEnabled: YES]; - - FlutterMethodCall* methodCall =[FlutterMethodCall methodCallWithMethodName:@"get" - arguments:nil]; + FlutterRestorationPlugin* restorationPlugin = + [[FlutterRestorationPlugin alloc] initWithChannel:restorationChannel restorationEnabled:YES]; + + FlutterMethodCall* methodCall = [FlutterMethodCall methodCallWithMethodName:@"get" arguments:nil]; __block id capturedResult; [restorationPlugin handleMethodCall:methodCall - result:^(id _Nullable result){ - capturedResult = result; + result:^(id _Nullable result) { + capturedResult = result; }]; XCTAssertNil(capturedResult); - + NSData* data = [@"testrestortiondata" dataUsingEncoding:NSUTF8StringEncoding]; - [restorationPlugin restorationData: data]; + [restorationPlugin restorationData:data]; XCTAssertEqual([capturedResult count], 2u); - XCTAssertEqual([capturedResult objectForKey: @"enabled"], @YES); - XCTAssertEqual([[capturedResult objectForKey: @"data"] data], data); + XCTAssertEqual([capturedResult objectForKey:@"enabled"], @YES); + XCTAssertEqual([[capturedResult objectForKey:@"data"] data], data); } - (void)testRestorationDisabledRespondsRightAway { - FlutterRestorationPlugin* restorationPlugin = [[FlutterRestorationPlugin alloc] initWithChannel: restorationChannel restorationEnabled: NO]; + FlutterRestorationPlugin* restorationPlugin = + [[FlutterRestorationPlugin alloc] initWithChannel:restorationChannel restorationEnabled:NO]; - FlutterMethodCall* methodCall =[FlutterMethodCall methodCallWithMethodName:@"get" - arguments:nil]; + FlutterMethodCall* methodCall = [FlutterMethodCall methodCallWithMethodName:@"get" arguments:nil]; __block id capturedResult; [restorationPlugin handleMethodCall:methodCall - result:^(id _Nullable result){ - capturedResult = result; + result:^(id _Nullable result) { + capturedResult = result; }]; XCTAssertEqual([capturedResult count], 1u); - XCTAssertEqual([capturedResult objectForKey: @"enabled"], @NO); + XCTAssertEqual([capturedResult objectForKey:@"enabled"], @NO); } - (void)testRespondsRightAwayWhenDataIsSet { - FlutterRestorationPlugin* restorationPlugin = [[FlutterRestorationPlugin alloc] initWithChannel: restorationChannel restorationEnabled: YES]; + FlutterRestorationPlugin* restorationPlugin = + [[FlutterRestorationPlugin alloc] initWithChannel:restorationChannel restorationEnabled:YES]; NSData* data = [@"testrestortiondata" dataUsingEncoding:NSUTF8StringEncoding]; - [restorationPlugin restorationData: data]; + [restorationPlugin restorationData:data]; __block id capturedResult; - FlutterMethodCall* methodCall =[FlutterMethodCall methodCallWithMethodName:@"get" - arguments:nil]; + FlutterMethodCall* methodCall = [FlutterMethodCall methodCallWithMethodName:@"get" arguments:nil]; [restorationPlugin handleMethodCall:methodCall - result:^(id _Nullable result){ - capturedResult = result; + result:^(id _Nullable result) { + capturedResult = result; }]; XCTAssertEqual([capturedResult count], 2u); - XCTAssertEqual([capturedResult objectForKey: @"enabled"], @YES); - XCTAssertEqual([[capturedResult objectForKey: @"data"] data], data); + XCTAssertEqual([capturedResult objectForKey:@"enabled"], @YES); + XCTAssertEqual([[capturedResult objectForKey:@"data"] data], data); } - (void)testRespondsWithNoDataWhenRestorationIsCompletedWithoutData { - FlutterRestorationPlugin* restorationPlugin = [[FlutterRestorationPlugin alloc] initWithChannel: restorationChannel restorationEnabled: YES]; - - FlutterMethodCall* methodCall =[FlutterMethodCall methodCallWithMethodName:@"get" - arguments:nil]; + FlutterRestorationPlugin* restorationPlugin = + [[FlutterRestorationPlugin alloc] initWithChannel:restorationChannel restorationEnabled:YES]; + + FlutterMethodCall* methodCall = [FlutterMethodCall methodCallWithMethodName:@"get" arguments:nil]; __block id capturedResult; [restorationPlugin handleMethodCall:methodCall - result:^(id _Nullable result){ - capturedResult = result; + result:^(id _Nullable result) { + capturedResult = result; }]; XCTAssertNil(capturedResult); - + [restorationPlugin restorationComplete]; XCTAssertEqual([capturedResult count], 1u); - XCTAssertEqual([capturedResult objectForKey: @"enabled"], @YES); + XCTAssertEqual([capturedResult objectForKey:@"enabled"], @YES); } - (void)testRespondsRightAwayWithNoDataWhenRestorationIsCompleted { - FlutterRestorationPlugin* restorationPlugin = [[FlutterRestorationPlugin alloc] initWithChannel: restorationChannel restorationEnabled: YES]; + FlutterRestorationPlugin* restorationPlugin = + [[FlutterRestorationPlugin alloc] initWithChannel:restorationChannel restorationEnabled:YES]; [restorationPlugin restorationComplete]; __block id capturedResult; - FlutterMethodCall* methodCall =[FlutterMethodCall methodCallWithMethodName:@"get" - arguments:nil]; + FlutterMethodCall* methodCall = [FlutterMethodCall methodCallWithMethodName:@"get" arguments:nil]; [restorationPlugin handleMethodCall:methodCall - result:^(id _Nullable result){ - capturedResult = result; + result:^(id _Nullable result) { + capturedResult = result; }]; XCTAssertEqual([capturedResult count], 1u); - XCTAssertEqual([capturedResult objectForKey: @"enabled"], @YES); + XCTAssertEqual([capturedResult objectForKey:@"enabled"], @YES); } - (void)testReturnsDataSetByFramework { - FlutterRestorationPlugin* restorationPlugin = [[FlutterRestorationPlugin alloc] initWithChannel: restorationChannel restorationEnabled: YES]; + FlutterRestorationPlugin* restorationPlugin = + [[FlutterRestorationPlugin alloc] initWithChannel:restorationChannel restorationEnabled:YES]; [restorationPlugin restorationComplete]; NSData* data = [@"testrestortiondata" dataUsingEncoding:NSUTF8StringEncoding]; - FlutterMethodCall* methodCall =[FlutterMethodCall methodCallWithMethodName:@"put" - arguments:[FlutterStandardTypedData typedDataWithBytes:data]]; + FlutterMethodCall* methodCall = [FlutterMethodCall + methodCallWithMethodName:@"put" + arguments:[FlutterStandardTypedData typedDataWithBytes:data]]; [restorationPlugin handleMethodCall:methodCall - result:^(id _Nullable result){ - XCTAssertNil(result); + result:^(id _Nullable result) { + XCTAssertNil(result); }]; XCTAssertEqual([restorationPlugin restorationData], data); } - (void)testRespondsWithDataSetByFramework { - FlutterRestorationPlugin* restorationPlugin = [[FlutterRestorationPlugin alloc] initWithChannel: restorationChannel restorationEnabled: YES]; + FlutterRestorationPlugin* restorationPlugin = + [[FlutterRestorationPlugin alloc] initWithChannel:restorationChannel restorationEnabled:YES]; [restorationPlugin restorationComplete]; - + NSData* data = [@"testrestortiondata" dataUsingEncoding:NSUTF8StringEncoding]; - FlutterMethodCall* methodCall =[FlutterMethodCall methodCallWithMethodName:@"put" - arguments:[FlutterStandardTypedData typedDataWithBytes:data]]; + FlutterMethodCall* methodCall = [FlutterMethodCall + methodCallWithMethodName:@"put" + arguments:[FlutterStandardTypedData typedDataWithBytes:data]]; [restorationPlugin handleMethodCall:methodCall - result:^(id _Nullable result){ - XCTAssertNil(result); + result:^(id _Nullable result) { + XCTAssertNil(result); }]; XCTAssertEqual([restorationPlugin restorationData], data); - + __block id capturedResult; - methodCall = [FlutterMethodCall methodCallWithMethodName:@"get" - arguments:nil]; + methodCall = [FlutterMethodCall methodCallWithMethodName:@"get" arguments:nil]; [restorationPlugin handleMethodCall:methodCall - result:^(id _Nullable result){ - capturedResult = result; + result:^(id _Nullable result) { + capturedResult = result; }]; XCTAssertEqual([capturedResult count], 2u); - XCTAssertEqual([capturedResult objectForKey: @"enabled"], @YES); - XCTAssertEqual([[capturedResult objectForKey: @"data"] data], data); + XCTAssertEqual([capturedResult objectForKey:@"enabled"], @YES); + XCTAssertEqual([[capturedResult objectForKey:@"data"] data], data); } - (void)testResetClearsData { - FlutterRestorationPlugin* restorationPlugin = [[FlutterRestorationPlugin alloc] initWithChannel: restorationChannel restorationEnabled: YES]; + FlutterRestorationPlugin* restorationPlugin = + [[FlutterRestorationPlugin alloc] initWithChannel:restorationChannel restorationEnabled:YES]; [restorationPlugin restorationComplete]; - + NSData* data = [@"testrestortiondata" dataUsingEncoding:NSUTF8StringEncoding]; - FlutterMethodCall* methodCall =[FlutterMethodCall methodCallWithMethodName:@"put" - arguments:[FlutterStandardTypedData typedDataWithBytes:data]]; + FlutterMethodCall* methodCall = [FlutterMethodCall + methodCallWithMethodName:@"put" + arguments:[FlutterStandardTypedData typedDataWithBytes:data]]; [restorationPlugin handleMethodCall:methodCall - result:^(id _Nullable result){ - XCTAssertNil(result); + result:^(id _Nullable result) { + XCTAssertNil(result); }]; XCTAssertEqual([restorationPlugin restorationData], data); - + [restorationPlugin reset]; XCTAssertNil([restorationPlugin restorationData]); - __block id capturedResult; - methodCall = [FlutterMethodCall methodCallWithMethodName:@"get" - arguments:nil]; + methodCall = [FlutterMethodCall methodCallWithMethodName:@"get" arguments:nil]; [restorationPlugin handleMethodCall:methodCall - result:^(id _Nullable result){ - capturedResult = result; + result:^(id _Nullable result) { + capturedResult = result; }]; XCTAssertEqual([capturedResult count], 1u); - XCTAssertEqual([capturedResult objectForKey: @"enabled"], @YES); + XCTAssertEqual([capturedResult objectForKey:@"enabled"], @YES); } @end diff --git a/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm b/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm index 039dda3d85b94..926ae61ea959e 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm @@ -1526,12 +1526,12 @@ - (void)scrollEvent:(UIPanGestureRecognizer*)recognizer API_AVAILABLE(ios(13.4)) #pragma mark - State Restoration -- (void)encodeRestorableStateWithCoder:(NSCoder *)coder { +- (void)encodeRestorableStateWithCoder:(NSCoder*)coder { NSData* restorationData = [[_engine.get() restorationPlugin] restorationData]; [coder encodeDataObject:restorationData]; } -- (void)decodeRestorableStateWithCoder:(NSCoder *)coder { +- (void)decodeRestorableStateWithCoder:(NSCoder*)coder { NSData* restorationData = [coder decodeDataObject]; [[_engine.get() restorationPlugin] restorationData:restorationData]; } From 5390cd401da9ad6e1ba40f2aac4d19807c92732f Mon Sep 17 00:00:00 2001 From: Michael Goderbauer Date: Thu, 7 Jan 2021 12:16:49 -0800 Subject: [PATCH 08/15] remove import --- .../platform/darwin/ios/framework/Source/FlutterAppDelegate.mm | 2 -- 1 file changed, 2 deletions(-) diff --git a/shell/platform/darwin/ios/framework/Source/FlutterAppDelegate.mm b/shell/platform/darwin/ios/framework/Source/FlutterAppDelegate.mm index 49f59c7b62456..cbb82597352b1 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterAppDelegate.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterAppDelegate.mm @@ -4,8 +4,6 @@ #import "flutter/shell/platform/darwin/ios/framework/Headers/FlutterAppDelegate.h" -#include - #import "flutter/fml/logging.h" #import "flutter/shell/platform/darwin/ios/framework/Headers/FlutterPluginAppLifeCycleDelegate.h" #import "flutter/shell/platform/darwin/ios/framework/Headers/FlutterViewController.h" From e5629561d02ba7a854fbcc45885d58ab09c3c5c9 Mon Sep 17 00:00:00 2001 From: Michael Goderbauer Date: Thu, 7 Jan 2021 13:19:45 -0800 Subject: [PATCH 09/15] format --- shell/platform/darwin/ios/framework/Headers/FlutterEngine.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/shell/platform/darwin/ios/framework/Headers/FlutterEngine.h b/shell/platform/darwin/ios/framework/Headers/FlutterEngine.h index b91a725d7ed85..5ebdaad5a89b9 100644 --- a/shell/platform/darwin/ios/framework/Headers/FlutterEngine.h +++ b/shell/platform/darwin/ios/framework/Headers/FlutterEngine.h @@ -153,7 +153,8 @@ FLUTTER_EXPORT * @param project The `FlutterDartProject` to run. * @param allowHeadlessExecution Whether or not to allow this instance to continue * running after passing a nil `FlutterViewController` to `-setViewController:`. - * @param restorationEnabled Whether state restoration is enabled. When true, the framework will wait for the attached view controller to provide restoration data. + * @param restorationEnabled Whether state restoration is enabled. When true, the framework will + * wait for the attached view controller to provide restoration data. */ - (instancetype)initWithName:(NSString*)labelPrefix project:(nullable FlutterDartProject*)project From 35d059e489f41f0018bc4aeb202c50f7a05b5cf7 Mon Sep 17 00:00:00 2001 From: Michael Goderbauer Date: Thu, 7 Jan 2021 14:38:03 -0800 Subject: [PATCH 10/15] review comments --- shell/platform/darwin/ios/framework/Headers/FlutterEngine.h | 2 +- .../ios/framework/Headers/FlutterHeadlessDartRunner.h | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/shell/platform/darwin/ios/framework/Headers/FlutterEngine.h b/shell/platform/darwin/ios/framework/Headers/FlutterEngine.h index 5ebdaad5a89b9..3139e741e095a 100644 --- a/shell/platform/darwin/ios/framework/Headers/FlutterEngine.h +++ b/shell/platform/darwin/ios/framework/Headers/FlutterEngine.h @@ -303,7 +303,7 @@ FLUTTER_EXPORT * Can be nil after `destroyContext` is called. * * @see [Restoration - * Channel](https://docs.flutter.io/flutter/services/SystemChannels/restoration-constant.html) + * Channel](https://api.flutter.dev/flutter/services/SystemChannels/restoration-constant.html) */ @property(nonatomic, readonly) FlutterMethodChannel* restorationChannel; diff --git a/shell/platform/darwin/ios/framework/Headers/FlutterHeadlessDartRunner.h b/shell/platform/darwin/ios/framework/Headers/FlutterHeadlessDartRunner.h index 418f10e404818..17391ff937644 100644 --- a/shell/platform/darwin/ios/framework/Headers/FlutterHeadlessDartRunner.h +++ b/shell/platform/darwin/ios/framework/Headers/FlutterHeadlessDartRunner.h @@ -34,7 +34,7 @@ FLUTTER_DEPRECATED("FlutterEngine should be used rather than FlutterHeadlessDart @interface FlutterHeadlessDartRunner : FlutterEngine /** - * Iniitalize this FlutterHeadlessDartRunner with a `FlutterDartProject`. + * Initialize this FlutterHeadlessDartRunner with a `FlutterDartProject`. * * If the FlutterDartProject is not specified, the FlutterHeadlessDartRunner will attempt to locate * the project in a default location. @@ -49,7 +49,7 @@ FLUTTER_DEPRECATED("FlutterEngine should be used rather than FlutterHeadlessDart - (instancetype)initWithName:(NSString*)labelPrefix project:(FlutterDartProject*)projectOrNil; /** - * Iniitalize this FlutterHeadlessDartRunner with a `FlutterDartProject`. + * Initialize this FlutterHeadlessDartRunner with a `FlutterDartProject`. * * If the FlutterDartProject is not specified, the FlutterHeadlessDartRunner will attempt to locate * the project in a default location. @@ -67,7 +67,7 @@ FLUTTER_DEPRECATED("FlutterEngine should be used rather than FlutterHeadlessDart allowHeadlessExecution:(BOOL)allowHeadlessExecution; /** - * Iniitalize this FlutterHeadlessDartRunner with a `FlutterDartProject`. + * Initialize this FlutterHeadlessDartRunner with a `FlutterDartProject`. * * If the FlutterDartProject is not specified, the FlutterHeadlessDartRunner will attempt to locate * the project in a default location. From 968e876955aeb541ba150fcac803f59d7ff902c5 Mon Sep 17 00:00:00 2001 From: Michael Goderbauer Date: Wed, 13 Jan 2021 14:38:02 -0800 Subject: [PATCH 11/15] review --- .../framework/Source/FlutterAppDelegate.mm | 9 ++--- .../Source/FlutterRestorationPlugin.h | 7 ++-- .../Source/FlutterRestorationPlugin.mm | 36 +++++++++---------- .../Source/FlutterRestorationPluginTest.mm | 14 ++++---- .../framework/Source/FlutterViewController.mm | 4 +-- 5 files changed, 33 insertions(+), 37 deletions(-) diff --git a/shell/platform/darwin/ios/framework/Source/FlutterAppDelegate.mm b/shell/platform/darwin/ios/framework/Source/FlutterAppDelegate.mm index cbb82597352b1..52105b943eeed 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterAppDelegate.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterAppDelegate.mm @@ -14,6 +14,7 @@ static NSString* kUIBackgroundMode = @"UIBackgroundModes"; static NSString* kRemoteNotificationCapabitiliy = @"remote-notification"; static NSString* kBackgroundFetchCapatibility = @"fetch"; +static NSString* kRestorationStateAppModificationKey = @"mod-date"; @interface FlutterAppDelegate () @property(nonatomic, copy) FlutterViewController* (^rootFlutterViewControllerGetter)(void); @@ -311,23 +312,23 @@ - (void)logCapabilityConfigurationWarningIfNeeded:(SEL)selector { #pragma mark - State Restoration - (BOOL)application:(UIApplication*)application shouldSaveApplicationState:(NSCoder*)coder { - [coder encodeInt64:self.lastAppModificationTime forKey:@"mod-date"]; + [coder encodeInt64:self.lastAppModificationTime forKey:kRestorationStateAppModificationKey]; return YES; } - (BOOL)application:(UIApplication*)application shouldRestoreApplicationState:(NSCoder*)coder { - int64_t stateDate = [coder decodeInt64ForKey:@"mod-date"]; + int64_t stateDate = [coder decodeInt64ForKey:kRestorationStateAppModificationKey]; return self.lastAppModificationTime == stateDate; } - (BOOL)application:(UIApplication*)application shouldSaveSecureApplicationState:(NSCoder*)coder { - [coder encodeInt64:self.lastAppModificationTime forKey:@"mod-date"]; + [coder encodeInt64:self.lastAppModificationTime forKey:kRestorationStateAppModificationKey]; return YES; } - (BOOL)application:(UIApplication*)application shouldRestoreSecureApplicationState:(NSCoder*)coder { - int64_t stateDate = [coder decodeInt64ForKey:@"mod-date"]; + int64_t stateDate = [coder decodeInt64ForKey:kRestorationStateAppModificationKey]; return self.lastAppModificationTime == stateDate; } diff --git a/shell/platform/darwin/ios/framework/Source/FlutterRestorationPlugin.h b/shell/platform/darwin/ios/framework/Source/FlutterRestorationPlugin.h index 7fdc9d42fc42c..b11ab0c451810 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterRestorationPlugin.h +++ b/shell/platform/darwin/ios/framework/Source/FlutterRestorationPlugin.h @@ -7,7 +7,6 @@ #import -#include "flutter/fml/memory/weak_ptr.h" #import "flutter/shell/platform/darwin/common/framework/Headers/FlutterChannels.h" @interface FlutterRestorationPlugin : NSObject @@ -16,9 +15,9 @@ - (instancetype)initWithChannel:(FlutterMethodChannel*)channel restorationEnabled:(BOOL)waitForData NS_DESIGNATED_INITIALIZER; -- (NSData*)restorationData; -- (void)restorationData:(NSData*)data; -- (void)restorationComplete; + +@property(nonatomic, retain) NSData* restorationData; +- (void)markRestorationComplete; - (void)reset; @end #endif // SHELL_PLATFORM_IOS_FRAMEWORK_SOURCE_FLUTTERRESTORATIONPLUGIN_H_ diff --git a/shell/platform/darwin/ios/framework/Source/FlutterRestorationPlugin.mm b/shell/platform/darwin/ios/framework/Source/FlutterRestorationPlugin.mm index c8ec4b37243d4..3d80e1b813b65 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterRestorationPlugin.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterRestorationPlugin.mm @@ -9,11 +9,12 @@ #include "flutter/fml/logging.h" +FLUTTER_ASSERT_NOT_ARC + @implementation FlutterRestorationPlugin { BOOL _waitForData; BOOL _restorationEnabled; FlutterResult _pendingRequest; - NSData* _restorationData; } - (instancetype)init { @@ -40,11 +41,7 @@ - (instancetype)initWithChannel:(FlutterMethodChannel*)channel - (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result { if ([[call method] isEqualToString:@"put"]) { FlutterStandardTypedData* data = [call arguments]; - NSData* newData = [[data data] retain]; - if (_restorationData != nil) { - [_restorationData release]; - } - _restorationData = newData; + _restorationData = [data data]; result(nil); } else if ([[call method] isEqualToString:@"get"]) { if (!_restorationEnabled || !_waitForData) { @@ -57,16 +54,8 @@ - (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result { } } -- (NSData*)restorationData { - return _restorationData; -} - -- (void)restorationData:(NSData*)data { - NSData* newData = [data retain]; - if (_restorationData != nil) { - [_restorationData release]; - } - _restorationData = newData; +- (void)setRestorationData:(NSData*)data { + _restorationData = data; _waitForData = NO; if (_pendingRequest != nil) { _pendingRequest([self dataForFramework]); @@ -75,7 +64,7 @@ - (void)restorationData:(NSData*)data { } } -- (void)restorationComplete { +- (void)markRestorationComplete { _waitForData = NO; if (_pendingRequest != nil) { NSAssert(_restorationEnabled, @"No request can be pending when restoration is disabled."); @@ -86,9 +75,6 @@ - (void)restorationComplete { } - (void)reset { - if (_restorationData != nil) { - [_restorationData release]; - } _restorationData = nil; if (_pendingRequest != nil) { [_pendingRequest release]; @@ -109,4 +95,14 @@ - (NSDictionary*)dataForFramework { }; } +-(void)dealloc { + if (_restorationData != nil) { + [_restorationData release]; + } + if (_pendingRequest != nil) { + [_pendingRequest release]; + } + [super dealloc]; +} + @end diff --git a/shell/platform/darwin/ios/framework/Source/FlutterRestorationPluginTest.mm b/shell/platform/darwin/ios/framework/Source/FlutterRestorationPluginTest.mm index 11d6f0324730a..ce1e6e55be71d 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterRestorationPluginTest.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterRestorationPluginTest.mm @@ -49,7 +49,7 @@ - (void)testRestorationEnabledWaitsForData { XCTAssertNil(capturedResult); NSData* data = [@"testrestortiondata" dataUsingEncoding:NSUTF8StringEncoding]; - [restorationPlugin restorationData:data]; + [restorationPlugin setRestorationData:data]; XCTAssertEqual([capturedResult count], 2u); XCTAssertEqual([capturedResult objectForKey:@"enabled"], @YES); XCTAssertEqual([[capturedResult objectForKey:@"data"] data], data); @@ -74,7 +74,7 @@ - (void)testRespondsRightAwayWhenDataIsSet { [[FlutterRestorationPlugin alloc] initWithChannel:restorationChannel restorationEnabled:YES]; NSData* data = [@"testrestortiondata" dataUsingEncoding:NSUTF8StringEncoding]; - [restorationPlugin restorationData:data]; + [restorationPlugin setRestorationData:data]; __block id capturedResult; FlutterMethodCall* methodCall = [FlutterMethodCall methodCallWithMethodName:@"get" arguments:nil]; @@ -99,7 +99,7 @@ - (void)testRespondsWithNoDataWhenRestorationIsCompletedWithoutData { }]; XCTAssertNil(capturedResult); - [restorationPlugin restorationComplete]; + [restorationPlugin markRestorationComplete]; XCTAssertEqual([capturedResult count], 1u); XCTAssertEqual([capturedResult objectForKey:@"enabled"], @YES); } @@ -108,7 +108,7 @@ - (void)testRespondsRightAwayWithNoDataWhenRestorationIsCompleted { FlutterRestorationPlugin* restorationPlugin = [[FlutterRestorationPlugin alloc] initWithChannel:restorationChannel restorationEnabled:YES]; - [restorationPlugin restorationComplete]; + [restorationPlugin markRestorationComplete]; __block id capturedResult; FlutterMethodCall* methodCall = [FlutterMethodCall methodCallWithMethodName:@"get" arguments:nil]; @@ -123,7 +123,7 @@ - (void)testRespondsRightAwayWithNoDataWhenRestorationIsCompleted { - (void)testReturnsDataSetByFramework { FlutterRestorationPlugin* restorationPlugin = [[FlutterRestorationPlugin alloc] initWithChannel:restorationChannel restorationEnabled:YES]; - [restorationPlugin restorationComplete]; + [restorationPlugin markRestorationComplete]; NSData* data = [@"testrestortiondata" dataUsingEncoding:NSUTF8StringEncoding]; FlutterMethodCall* methodCall = [FlutterMethodCall @@ -139,7 +139,7 @@ - (void)testReturnsDataSetByFramework { - (void)testRespondsWithDataSetByFramework { FlutterRestorationPlugin* restorationPlugin = [[FlutterRestorationPlugin alloc] initWithChannel:restorationChannel restorationEnabled:YES]; - [restorationPlugin restorationComplete]; + [restorationPlugin markRestorationComplete]; NSData* data = [@"testrestortiondata" dataUsingEncoding:NSUTF8StringEncoding]; FlutterMethodCall* methodCall = [FlutterMethodCall @@ -165,7 +165,7 @@ - (void)testRespondsWithDataSetByFramework { - (void)testResetClearsData { FlutterRestorationPlugin* restorationPlugin = [[FlutterRestorationPlugin alloc] initWithChannel:restorationChannel restorationEnabled:YES]; - [restorationPlugin restorationComplete]; + [restorationPlugin markRestorationComplete]; NSData* data = [@"testrestortiondata" dataUsingEncoding:NSUTF8StringEncoding]; FlutterMethodCall* methodCall = [FlutterMethodCall diff --git a/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm b/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm index 926ae61ea959e..dc4d0b164cdef 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm @@ -655,7 +655,7 @@ - (void)viewWillAppear:(BOOL)animated { [self surfaceUpdated:YES]; } [[_engine.get() lifecycleChannel] sendMessage:@"AppLifecycleState.inactive"]; - [[_engine.get() restorationPlugin] restorationComplete]; + [[_engine.get() restorationPlugin] markRestorationComplete]; [super viewWillAppear:animated]; } @@ -1533,7 +1533,7 @@ - (void)encodeRestorableStateWithCoder:(NSCoder*)coder { - (void)decodeRestorableStateWithCoder:(NSCoder*)coder { NSData* restorationData = [coder decodeDataObject]; - [[_engine.get() restorationPlugin] restorationData:restorationData]; + [[_engine.get() restorationPlugin] setRestorationData:restorationData]; } - (FlutterRestorationPlugin*)restorationPlugin { From 55599267251a2bd2c6ff8d98c4d0837a529ad0ce Mon Sep 17 00:00:00 2001 From: Michael Goderbauer Date: Wed, 13 Jan 2021 15:18:12 -0800 Subject: [PATCH 12/15] format --- .../darwin/ios/framework/Source/FlutterRestorationPlugin.h | 1 - .../darwin/ios/framework/Source/FlutterRestorationPlugin.mm | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/shell/platform/darwin/ios/framework/Source/FlutterRestorationPlugin.h b/shell/platform/darwin/ios/framework/Source/FlutterRestorationPlugin.h index b11ab0c451810..4832ed7d75844 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterRestorationPlugin.h +++ b/shell/platform/darwin/ios/framework/Source/FlutterRestorationPlugin.h @@ -15,7 +15,6 @@ - (instancetype)initWithChannel:(FlutterMethodChannel*)channel restorationEnabled:(BOOL)waitForData NS_DESIGNATED_INITIALIZER; - @property(nonatomic, retain) NSData* restorationData; - (void)markRestorationComplete; - (void)reset; diff --git a/shell/platform/darwin/ios/framework/Source/FlutterRestorationPlugin.mm b/shell/platform/darwin/ios/framework/Source/FlutterRestorationPlugin.mm index 3d80e1b813b65..5ddf3b048d6ac 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterRestorationPlugin.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterRestorationPlugin.mm @@ -95,7 +95,7 @@ - (NSDictionary*)dataForFramework { }; } --(void)dealloc { +- (void)dealloc { if (_restorationData != nil) { [_restorationData release]; } From fbcb797b306aa3378422ba7e8f7023364311e7a1 Mon Sep 17 00:00:00 2001 From: Michael Goderbauer Date: Wed, 13 Jan 2021 16:12:06 -0800 Subject: [PATCH 13/15] another review --- .../framework/Source/FlutterAppDelegate.mm | 12 +++-- .../Source/FlutterRestorationPlugin.h | 2 +- .../Source/FlutterRestorationPlugin.mm | 49 +++++++++---------- 3 files changed, 32 insertions(+), 31 deletions(-) diff --git a/shell/platform/darwin/ios/framework/Source/FlutterAppDelegate.mm b/shell/platform/darwin/ios/framework/Source/FlutterAppDelegate.mm index 52105b943eeed..72fa8344f64a6 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterAppDelegate.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterAppDelegate.mm @@ -11,10 +11,10 @@ #import "flutter/shell/platform/darwin/ios/framework/Source/FlutterEngine_Internal.h" #import "flutter/shell/platform/darwin/ios/framework/Source/FlutterPluginAppLifeCycleDelegate_internal.h" -static NSString* kUIBackgroundMode = @"UIBackgroundModes"; -static NSString* kRemoteNotificationCapabitiliy = @"remote-notification"; -static NSString* kBackgroundFetchCapatibility = @"fetch"; -static NSString* kRestorationStateAppModificationKey = @"mod-date"; +static NSString* const kUIBackgroundMode = @"UIBackgroundModes"; +static NSString* const kRemoteNotificationCapabitiliy = @"remote-notification"; +static NSString* const kBackgroundFetchCapatibility = @"fetch"; +static NSString* const kRestorationStateAppModificationKey = @"mod-date"; @interface FlutterAppDelegate () @property(nonatomic, copy) FlutterViewController* (^rootFlutterViewControllerGetter)(void); @@ -334,9 +334,11 @@ - (BOOL)application:(UIApplication*)application - (int64_t)lastAppModificationTime { NSDate* fileDate; + NSError* error = nil; [[[NSBundle mainBundle] executableURL] getResourceValue:&fileDate forKey:NSURLContentModificationDateKey - error:nil]; + error:&error]; + NSAssert(error == nil, @"Cannot obtain modification date of main bundle: %@", error); return [fileDate timeIntervalSince1970]; } diff --git a/shell/platform/darwin/ios/framework/Source/FlutterRestorationPlugin.h b/shell/platform/darwin/ios/framework/Source/FlutterRestorationPlugin.h index 4832ed7d75844..36311be2340fc 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterRestorationPlugin.h +++ b/shell/platform/darwin/ios/framework/Source/FlutterRestorationPlugin.h @@ -15,7 +15,7 @@ - (instancetype)initWithChannel:(FlutterMethodChannel*)channel restorationEnabled:(BOOL)waitForData NS_DESIGNATED_INITIALIZER; -@property(nonatomic, retain) NSData* restorationData; +@property(nonatomic, strong) NSData* restorationData; - (void)markRestorationComplete; - (void)reset; @end diff --git a/shell/platform/darwin/ios/framework/Source/FlutterRestorationPlugin.mm b/shell/platform/darwin/ios/framework/Source/FlutterRestorationPlugin.mm index 5ddf3b048d6ac..0ff207e3b61db 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterRestorationPlugin.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterRestorationPlugin.mm @@ -11,10 +11,13 @@ FLUTTER_ASSERT_NOT_ARC +@interface FlutterRestorationPlugin () +@property(nonatomic, copy) FlutterResult pendingRequest; +@end + @implementation FlutterRestorationPlugin { BOOL _waitForData; BOOL _restorationEnabled; - FlutterResult _pendingRequest; } - (instancetype)init { @@ -40,68 +43,64 @@ - (instancetype)initWithChannel:(FlutterMethodChannel*)channel - (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result { if ([[call method] isEqualToString:@"put"]) { + NSAssert(self.pendingRequest == nil, @"Cannot put data while a get request is pending."); FlutterStandardTypedData* data = [call arguments]; - _restorationData = [data data]; + self.restorationData = [data data]; result(nil); } else if ([[call method] isEqualToString:@"get"]) { if (!_restorationEnabled || !_waitForData) { result([self dataForFramework]); return; } - _pendingRequest = [result retain]; + NSAssert(self.pendingRequest == nil, @"There can only be one pending request."); + self.pendingRequest = result; } else { result(FlutterMethodNotImplemented); } } - (void)setRestorationData:(NSData*)data { - _restorationData = data; + if (data != _restorationData) { + [_restorationData release]; + _restorationData = [data retain]; + } _waitForData = NO; - if (_pendingRequest != nil) { - _pendingRequest([self dataForFramework]); - [_pendingRequest release]; - _pendingRequest = nil; + if (self.pendingRequest != nil) { + self.pendingRequest([self dataForFramework]); + self.pendingRequest = nil; } } - (void)markRestorationComplete { _waitForData = NO; - if (_pendingRequest != nil) { + if (self.pendingRequest != nil) { NSAssert(_restorationEnabled, @"No request can be pending when restoration is disabled."); - _pendingRequest([self dataForFramework]); - [_pendingRequest release]; - _pendingRequest = nil; + self.pendingRequest([self dataForFramework]); + self.pendingRequest = nil; } } - (void)reset { - _restorationData = nil; - if (_pendingRequest != nil) { - [_pendingRequest release]; - } - _pendingRequest = nil; + self.pendingRequest = nil; + self.restorationData = nil; } - (NSDictionary*)dataForFramework { if (!_restorationEnabled) { return @{@"enabled" : @NO}; } - if (_restorationData == nil) { + if (self.restorationData == nil) { return @{@"enabled" : @YES}; } return @{ @"enabled" : @YES, - @"data" : [FlutterStandardTypedData typedDataWithBytes:_restorationData] + @"data" : [FlutterStandardTypedData typedDataWithBytes:self.restorationData] }; } - (void)dealloc { - if (_restorationData != nil) { - [_restorationData release]; - } - if (_pendingRequest != nil) { - [_pendingRequest release]; - } + [_restorationData release]; + [_pendingRequest release]; [super dealloc]; } From c08e07f390bd5290e5f265ea87d2a136dbe7ca68 Mon Sep 17 00:00:00 2001 From: Michael Goderbauer Date: Thu, 14 Jan 2021 13:27:29 -0800 Subject: [PATCH 14/15] format --- .../framework/Source/FlutterViewController.mm | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm b/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm index dc4d0b164cdef..52ea8f5c69f87 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm @@ -1523,21 +1523,21 @@ - (void)scrollEvent:(UIPanGestureRecognizer*)recognizer API_AVAILABLE(ios(13.4)) packet->SetPointerData(/*index=*/0, pointer_data); [_engine.get() dispatchPointerDataPacket:std::move(packet)]; - + #pragma mark - State Restoration -- (void)encodeRestorableStateWithCoder:(NSCoder*)coder { - NSData* restorationData = [[_engine.get() restorationPlugin] restorationData]; - [coder encodeDataObject:restorationData]; -} + -(void)encodeRestorableStateWithCoder : (NSCoder*)coder { + NSData* restorationData = [[_engine.get() restorationPlugin] restorationData]; + [coder encodeDataObject:restorationData]; + } -- (void)decodeRestorableStateWithCoder:(NSCoder*)coder { - NSData* restorationData = [coder decodeDataObject]; - [[_engine.get() restorationPlugin] setRestorationData:restorationData]; -} + -(void)decodeRestorableStateWithCoder : (NSCoder*)coder { + NSData* restorationData = [coder decodeDataObject]; + [[_engine.get() restorationPlugin] setRestorationData:restorationData]; + } -- (FlutterRestorationPlugin*)restorationPlugin { - return [_engine.get() restorationPlugin]; -} + -(FlutterRestorationPlugin*)restorationPlugin { + return [_engine.get() restorationPlugin]; + } -@end + @end From 78fe7c591ee065f3ec7606cf3b1cd4097e4b73f4 Mon Sep 17 00:00:00 2001 From: Michael Goderbauer Date: Thu, 14 Jan 2021 13:42:59 -0800 Subject: [PATCH 15/15] merge conflict --- .../framework/Source/FlutterViewController.mm | 25 ++++++++++--------- 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm b/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm index 52ea8f5c69f87..df26adc95048f 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm @@ -1523,21 +1523,22 @@ - (void)scrollEvent:(UIPanGestureRecognizer*)recognizer API_AVAILABLE(ios(13.4)) packet->SetPointerData(/*index=*/0, pointer_data); [_engine.get() dispatchPointerDataPacket:std::move(packet)]; +} #pragma mark - State Restoration - -(void)encodeRestorableStateWithCoder : (NSCoder*)coder { - NSData* restorationData = [[_engine.get() restorationPlugin] restorationData]; - [coder encodeDataObject:restorationData]; - } +- (void)encodeRestorableStateWithCoder:(NSCoder*)coder { + NSData* restorationData = [[_engine.get() restorationPlugin] restorationData]; + [coder encodeDataObject:restorationData]; +} - -(void)decodeRestorableStateWithCoder : (NSCoder*)coder { - NSData* restorationData = [coder decodeDataObject]; - [[_engine.get() restorationPlugin] setRestorationData:restorationData]; - } +- (void)decodeRestorableStateWithCoder:(NSCoder*)coder { + NSData* restorationData = [coder decodeDataObject]; + [[_engine.get() restorationPlugin] setRestorationData:restorationData]; +} - -(FlutterRestorationPlugin*)restorationPlugin { - return [_engine.get() restorationPlugin]; - } +- (FlutterRestorationPlugin*)restorationPlugin { + return [_engine.get() restorationPlugin]; +} - @end +@end