-
Notifications
You must be signed in to change notification settings - Fork 6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
State Restoration for iOS #23495
State Restoration for iOS #23495
Conversation
3c945f4
to
9c9931a
Compare
shell/platform/darwin/ios/framework/Headers/FlutterHeadlessDartRunner.h
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A few initial comments. Overall looks good. @gaaclarke for the OCMock test, which I'm less familiar with.
#pragma mark - State Restoration | ||
|
||
- (BOOL)application:(UIApplication*)application shouldSaveApplicationState:(NSCoder*)coder { | ||
[coder encodeInt64:self.lastAppModificationTime forKey:@"mod-date"]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Optional: not used much but consider yanking this to a const. Sadly, can't use constexpr since it's an NSString.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well it is duplicated across the file so I think it's a good idea.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
|
||
#import <UIKit/UIKit.h> | ||
|
||
#include "flutter/fml/memory/weak_ptr.h" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Doesn't look like you're using weak_ptr here (anymore).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removed import.
restorationEnabled:(BOOL)waitForData NS_DESIGNATED_INITIALIZER; | ||
|
||
- (NSData*)restorationData; | ||
- (void)restorationData:(NSData*)data; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be - (void)setRestorationData:(NSData*)data;
. The getter is named correctly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use a property as previously mentioned.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
|
||
- (NSData*)restorationData; | ||
- (void)restorationData:(NSData*)data; | ||
- (void)restorationComplete; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be setRestorationComplete
or similar.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Renamed.
Added @gaaclarke for additional set of eyes, particularly around the OCMock test. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The tests look good to me. I just had some comments mostly around non-idiomatic code and the usage of properties.
NSDate* fileDate; | ||
[[[NSBundle mainBundle] executableURL] getResourceValue:&fileDate | ||
forKey:NSURLContentModificationDateKey | ||
error:nil]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should probably not gobble up this error. Its worth having an assert at least.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I missed this comment earlier, will fix after meeting.
- (instancetype)initWithChannel:(FlutterMethodChannel*)channel | ||
restorationEnabled:(BOOL)waitForData NS_DESIGNATED_INITIALIZER; | ||
|
||
- (NSData*)restorationData; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Idiomatic objc would use a property for this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
changed to property.
restorationEnabled:(BOOL)waitForData NS_DESIGNATED_INITIALIZER; | ||
|
||
- (NSData*)restorationData; | ||
- (void)restorationData:(NSData*)data; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use a property as previously mentioned.
// found in the LICENSE file. | ||
|
||
#import "flutter/shell/platform/darwin/ios/framework/Source/FlutterRestorationPlugin.h" | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please assert ARC or non ARC at the top. There are macros in FlutterMacros.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You mean FLUTTER_ASSERT_NOT_ARC or FLUTTER_ASSERT_ARC? In existing code I am only seeing those used in test code. Should they also appear in this non-test code?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added FLUTTER_ASSERT_NOT_ARC.
BOOL _waitForData; | ||
BOOL _restorationEnabled; | ||
FlutterResult _pendingRequest; | ||
NSData* _restorationData; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You need to add a dealloc to this class that deletes this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added.
if ([[call method] isEqualToString:@"put"]) { | ||
FlutterStandardTypedData* data = [call arguments]; | ||
NSData* newData = [[data data] retain]; | ||
if (_restorationData != nil) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you use properties you don't have to do this manual reference counting work.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removed.
} | ||
_restorationData = newData; | ||
result(nil); | ||
} else if ([[call method] isEqualToString:@"get"]) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is no call to result in this method.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The call to result is delayed until we have something to send over, see _pendingResult.
if (_restorationData != nil) { | ||
[_restorationData release]; | ||
} | ||
_restorationData = newData; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Another place where properties will make your life easier.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removed.
XCTAssertNil([restorationPlugin restorationData]); | ||
|
||
__block id capturedResult; | ||
methodCall = [FlutterMethodCall methodCallWithMethodName:@"get" arguments:nil]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Optional: It would be nice if these method names where placed as consts in the header so we don't have to duplicate them. No one should have to refer to them by string literal.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the review. Addressed all comments. PTAL.
#pragma mark - State Restoration | ||
|
||
- (BOOL)application:(UIApplication*)application shouldSaveApplicationState:(NSCoder*)coder { | ||
[coder encodeInt64:self.lastAppModificationTime forKey:@"mod-date"]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
|
||
#import <UIKit/UIKit.h> | ||
|
||
#include "flutter/fml/memory/weak_ptr.h" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removed import.
restorationEnabled:(BOOL)waitForData NS_DESIGNATED_INITIALIZER; | ||
|
||
- (NSData*)restorationData; | ||
- (void)restorationData:(NSData*)data; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
|
||
- (NSData*)restorationData; | ||
- (void)restorationData:(NSData*)data; | ||
- (void)restorationComplete; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Renamed.
// found in the LICENSE file. | ||
|
||
#import "flutter/shell/platform/darwin/ios/framework/Source/FlutterRestorationPlugin.h" | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You mean FLUTTER_ASSERT_NOT_ARC or FLUTTER_ASSERT_ARC? In existing code I am only seeing those used in test code. Should they also appear in this non-test code?
if ([[call method] isEqualToString:@"put"]) { | ||
FlutterStandardTypedData* data = [call arguments]; | ||
NSData* newData = [[data data] retain]; | ||
if (_restorationData != nil) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removed.
} | ||
_restorationData = newData; | ||
result(nil); | ||
} else if ([[call method] isEqualToString:@"get"]) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The call to result is delayed until we have something to send over, see _pendingResult.
if (_restorationData != nil) { | ||
[_restorationData release]; | ||
} | ||
_restorationData = newData; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removed.
BOOL _waitForData; | ||
BOOL _restorationEnabled; | ||
FlutterResult _pendingRequest; | ||
NSData* _restorationData; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added.
// found in the LICENSE file. | ||
|
||
#import "flutter/shell/platform/darwin/ios/framework/Source/FlutterRestorationPlugin.h" | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added FLUTTER_ASSERT_NOT_ARC.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks looking much better, lgtm modulo changing pendingRequest to a property as well.
PS declare the property in the .mm file with a class extension.
@@ -14,6 +14,7 @@ | |||
static NSString* kUIBackgroundMode = @"UIBackgroundModes"; | |||
static NSString* kRemoteNotificationCapabitiliy = @"remote-notification"; | |||
static NSString* kBackgroundFetchCapatibility = @"fetch"; | |||
static NSString* kRestorationStateAppModificationKey = @"mod-date"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These should really be static NSString* const
, sorry I know you didn't set the precedent =(
- (instancetype)initWithChannel:(FlutterMethodChannel*)channel | ||
restorationEnabled:(BOOL)waitForData NS_DESIGNATED_INITIALIZER; | ||
|
||
@property(nonatomic, retain) NSData* restorationData; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
s/retain/strong for forward compatibility with ARC
} | ||
|
||
- (void)dealloc { | ||
if (_restorationData != nil) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
there is no need to do a nil check here, calls to nil are ignored in objective-c
result([self dataForFramework]); | ||
return; | ||
} | ||
_pendingRequest = [result retain]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a leak, you should switch pendingRequest to a property and used self.pendingRequest = result;
The property should be copy
for blocks. In more cases your code will clean up once you turn this to a property, too. Sorry I didn't catch it earlier.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM thanks!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lgtm!
This pull request is not suitable for automatic merging in its current state.
|
e6fee6c
to
7c2858f
Compare
This pull request is not suitable for automatic merging in its current state.
|
7c2858f
to
c08e07f
Compare
Description
Wires up state restoration in the iOS embedder. The same has been done for Android in #18042.
Related Issues
Fixes flutter/flutter#62915.
Tests
I added the following tests:
Checklist
Before you create this PR confirm that it meets all requirements listed below by checking the relevant checkboxes (
[x]
). This will ensure a smooth and quick review process.Reviewer Checklist
Breaking Change
Did any tests fail when you ran them? Please read handling breaking changes.