Skip to content
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

Merged
merged 15 commits into from Jan 14, 2021
Merged

Conversation

goderbauer
Copy link
Member

@goderbauer goderbauer commented Jan 7, 2021

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:

  • Test for the new RestorationPlugin

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.

  • I read the contributor guide and followed the process outlined there for submitting PRs.
  • I signed the CLA.
  • I read and followed the C++, Objective-C, Java style guides for the engine.
  • I read the tree hygiene wiki page, which explains my responsibilities.
  • I updated/added relevant documentation.
  • All existing and new tests are passing.
  • I am willing to follow-up on review comments in a timely manner.

Reviewer Checklist

Breaking Change

Did any tests fail when you ran them? Please read handling breaking changes.

@google-cla google-cla bot added the cla: yes label Jan 7, 2021
@goderbauer goderbauer changed the title Iosrestoration State Restoration for iOS Jan 7, 2021
Copy link
Member

@cbracken cbracken left a 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"];
Copy link
Member

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.

Copy link
Member

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.

Copy link
Member Author

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"
Copy link
Member

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).

Copy link
Member Author

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;
Copy link
Member

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.

Copy link
Member

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.

Copy link
Member Author

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;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Renamed.

@cbracken
Copy link
Member

Added @gaaclarke for additional set of eyes, particularly around the OCMock test.

Copy link
Member

@gaaclarke gaaclarke left a 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];
Copy link
Member

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.

Copy link
Member Author

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;
Copy link
Member

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.

Copy link
Member Author

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;
Copy link
Member

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"

Copy link
Member

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.

Copy link
Member Author

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?

Copy link
Member Author

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;
Copy link
Member

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.

Copy link
Member Author

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) {
Copy link
Member

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.

Copy link
Member Author

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"]) {
Copy link
Member

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.

Copy link
Member Author

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;
Copy link
Member

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.

Copy link
Member Author

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];
Copy link
Member

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.

Copy link
Member Author

@goderbauer goderbauer left a 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"];
Copy link
Member Author

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"
Copy link
Member Author

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;
Copy link
Member Author

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;
Copy link
Member Author

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"

Copy link
Member Author

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) {
Copy link
Member Author

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"]) {
Copy link
Member Author

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;
Copy link
Member Author

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;
Copy link
Member Author

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"

Copy link
Member Author

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.

Copy link
Member

@gaaclarke gaaclarke left a 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";
Copy link
Member

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;
Copy link
Member

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) {
Copy link
Member

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];
Copy link
Member

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.

Copy link
Member

@gaaclarke gaaclarke left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM thanks!

Copy link
Member

@cbracken cbracken left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm!

@goderbauer goderbauer added the waiting for tree to go green This PR is approved and tested, but waiting for the tree to be green to land. label Jan 14, 2021
@fluttergithubbot
Copy link
Contributor

This pull request is not suitable for automatic merging in its current state.

  • The status or check suite Mac Host Engine has failed. Please fix the issues identified (or deflake) before re-applying this label.

@fluttergithubbot fluttergithubbot removed the waiting for tree to go green This PR is approved and tested, but waiting for the tree to be green to land. label Jan 14, 2021
@goderbauer goderbauer added the waiting for tree to go green This PR is approved and tested, but waiting for the tree to be green to land. label Jan 14, 2021
@fluttergithubbot
Copy link
Contributor

This pull request is not suitable for automatic merging in its current state.

  • The status or check suite Linux Web Engine has failed. Please fix the issues identified (or deflake) before re-applying this label.

@fluttergithubbot fluttergithubbot removed the waiting for tree to go green This PR is approved and tested, but waiting for the tree to be green to land. label Jan 14, 2021
@goderbauer goderbauer added the waiting for tree to go green This PR is approved and tested, but waiting for the tree to be green to land. label Jan 14, 2021
@fluttergithubbot fluttergithubbot merged commit 0123541 into flutter:master Jan 14, 2021
engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request Jan 15, 2021
gspencergoog pushed a commit to gspencergoog/engine that referenced this pull request Jan 20, 2021
@goderbauer goderbauer deleted the iosrestoration branch January 22, 2021 17:59
hjfreyer pushed a commit to hjfreyer/engine that referenced this pull request Mar 22, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
cla: yes platform-ios waiting for tree to go green This PR is approved and tested, but waiting for the tree to be green to land.
Projects
None yet
5 participants