Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit 3e1d857

Browse files
committed
Refactor and migrate FlutterUndoManagerPlugin to ARC
1 parent aa6f741 commit 3e1d857

File tree

7 files changed

+75
-82
lines changed

7 files changed

+75
-82
lines changed

shell/platform/darwin/ios/BUILD.gn

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,9 @@ source_set("flutter_framework_source_arc") {
8484
"framework/Source/FlutterTextureRegistryRelay.mm",
8585
"framework/Source/FlutterUIPressProxy.h",
8686
"framework/Source/FlutterUIPressProxy.mm",
87+
"framework/Source/FlutterUndoManagerDelegate.h",
88+
"framework/Source/FlutterUndoManagerPlugin.h",
89+
"framework/Source/FlutterUndoManagerPlugin.mm",
8790
"framework/Source/KeyCodeMap.g.mm",
8891
"framework/Source/KeyCodeMap_Internal.h",
8992
"framework/Source/UIViewController+FlutterScreenAndSceneIfLoaded.h",
@@ -157,9 +160,6 @@ source_set("flutter_framework_source") {
157160
"framework/Source/FlutterPluginAppLifeCycleDelegate.mm",
158161
"framework/Source/FlutterSemanticsScrollView.h",
159162
"framework/Source/FlutterSemanticsScrollView.mm",
160-
"framework/Source/FlutterUndoManagerDelegate.h",
161-
"framework/Source/FlutterUndoManagerPlugin.h",
162-
"framework/Source/FlutterUndoManagerPlugin.mm",
163163
"framework/Source/FlutterView.h",
164164
"framework/Source/FlutterView.mm",
165165
"framework/Source/FlutterViewController.mm",

shell/platform/darwin/ios/framework/Source/FlutterEngine.mm

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -430,7 +430,6 @@ - (void)setViewController:(FlutterViewController*)viewController {
430430
[self maybeSetupPlatformViewChannels];
431431
[self updateDisplays];
432432
_textInputPlugin.get().viewController = viewController;
433-
_undoManagerPlugin.get().viewController = viewController;
434433

435434
if (viewController) {
436435
__block FlutterEngine* blockSelf = self;
@@ -465,7 +464,6 @@ - (void)setFlutterViewControllerWillDeallocObserver:(id<NSObject>)observer {
465464
- (void)notifyViewControllerDeallocated {
466465
[[self lifecycleChannel] sendMessage:@"AppLifecycleState.detached"];
467466
_textInputPlugin.get().viewController = nil;
468-
_undoManagerPlugin.get().viewController = nil;
469467
if (!_allowHeadlessExecution) {
470468
[self destroyContext];
471469
} else if (_shell) {

shell/platform/darwin/ios/framework/Source/FlutterUndoManagerDelegate.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77

88
#import <Foundation/Foundation.h>
99

10+
#import "flutter/shell/platform/darwin/ios/framework/Source/FlutterTextInputPlugin.h"
11+
1012
NS_ASSUME_NONNULL_BEGIN
1113

1214
typedef NS_ENUM(NSInteger, FlutterUndoRedoDirection) {
@@ -19,8 +21,14 @@ typedef NS_ENUM(NSInteger, FlutterUndoRedoDirection) {
1921
@class FlutterUndoManagerPlugin;
2022

2123
@protocol FlutterUndoManagerDelegate <NSObject>
24+
25+
@property(nonatomic, weak) UIResponder* viewController;
26+
27+
- (FlutterTextInputPlugin*)textInputPlugin;
28+
2229
- (void)flutterUndoManagerPlugin:(FlutterUndoManagerPlugin*)undoManagerPlugin
2330
handleUndoWithDirection:(FlutterUndoRedoDirection)direction;
31+
2432
@end
2533
NS_ASSUME_NONNULL_END
2634

shell/platform/darwin/ios/framework/Source/FlutterUndoManagerPlugin.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,11 @@
77

88
#import <UIKit/UIKit.h>
99

10-
#import "flutter/fml/memory/weak_ptr.h"
1110
#import "flutter/shell/platform/darwin/common/framework/Headers/FlutterChannels.h"
12-
#import "flutter/shell/platform/darwin/ios/framework/Headers/FlutterViewController.h"
1311
#import "flutter/shell/platform/darwin/ios/framework/Source/FlutterUndoManagerDelegate.h"
1412

1513
@interface FlutterUndoManagerPlugin : NSObject
1614

17-
@property(nonatomic, assign) FlutterViewController* viewController;
18-
1915
- (instancetype)init NS_UNAVAILABLE;
2016
+ (instancetype)new NS_UNAVAILABLE;
2117

shell/platform/darwin/ios/framework/Source/FlutterUndoManagerPlugin.mm

Lines changed: 38 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,8 @@
33
// found in the LICENSE file.
44

55
#import "flutter/shell/platform/darwin/ios/framework/Source/FlutterUndoManagerPlugin.h"
6-
#import "flutter/shell/platform/darwin/ios/framework/Source/FlutterEngine_Internal.h"
76

8-
#import <Foundation/Foundation.h>
9-
#import <UIKit/UIKit.h>
10-
11-
#include "flutter/fml/logging.h"
7+
#import "flutter/shell/platform/darwin/ios/framework/Source/FlutterTextInputPlugin.h"
128

139
#pragma mark - UndoManager channel method names.
1410
static NSString* const kSetUndoStateMethod = @"UndoManager.setUndoState";
@@ -17,15 +13,16 @@
1713
static NSString* const kCanUndo = @"canUndo";
1814
static NSString* const kCanRedo = @"canRedo";
1915

20-
@implementation FlutterUndoManagerPlugin {
21-
id<FlutterUndoManagerDelegate> _undoManagerDelegate;
22-
}
16+
@interface FlutterUndoManagerPlugin ()
17+
@property(nonatomic, weak, readonly) id<FlutterUndoManagerDelegate> undoManagerDelegate;
18+
@end
19+
20+
@implementation FlutterUndoManagerPlugin
2321

2422
- (instancetype)initWithDelegate:(id<FlutterUndoManagerDelegate>)undoManagerDelegate {
2523
self = [super init];
2624

2725
if (self) {
28-
// `_undoManagerDelegate` is a weak reference because it should retain FlutterUndoManagerPlugin.
2926
_undoManagerDelegate = undoManagerDelegate;
3027
}
3128

@@ -34,7 +31,6 @@ - (instancetype)initWithDelegate:(id<FlutterUndoManagerDelegate>)undoManagerDele
3431

3532
- (void)dealloc {
3633
[self resetUndoManager];
37-
[super dealloc];
3834
}
3935

4036
- (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result {
@@ -49,45 +45,47 @@ - (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result {
4945
}
5046

5147
- (NSUndoManager*)undoManager {
52-
return _viewController.undoManager;
48+
return self.undoManagerDelegate.viewController.undoManager;
5349
}
5450

5551
- (void)resetUndoManager API_AVAILABLE(ios(9.0)) {
5652
[[self undoManager] removeAllActionsWithTarget:self];
5753
}
5854

5955
- (void)registerUndoWithDirection:(FlutterUndoRedoDirection)direction API_AVAILABLE(ios(9.0)) {
60-
[[self undoManager] beginUndoGrouping];
61-
[[self undoManager] registerUndoWithTarget:self
62-
handler:^(id target) {
63-
// Register undo with opposite direction.
64-
FlutterUndoRedoDirection newDirection =
65-
(direction == FlutterUndoRedoDirectionRedo)
66-
? FlutterUndoRedoDirectionUndo
67-
: FlutterUndoRedoDirectionRedo;
68-
[target registerUndoWithDirection:newDirection];
69-
// Invoke method on delegate.
70-
[_undoManagerDelegate flutterUndoManagerPlugin:self
71-
handleUndoWithDirection:direction];
72-
}];
73-
[[self undoManager] endUndoGrouping];
56+
NSUndoManager* undoManager = [self undoManager];
57+
[undoManager beginUndoGrouping];
58+
[undoManager registerUndoWithTarget:self
59+
handler:^(id target) {
60+
// Register undo with opposite direction.
61+
FlutterUndoRedoDirection newDirection =
62+
(direction == FlutterUndoRedoDirectionRedo)
63+
? FlutterUndoRedoDirectionUndo
64+
: FlutterUndoRedoDirectionRedo;
65+
[target registerUndoWithDirection:newDirection];
66+
// Invoke method on delegate.
67+
[self.undoManagerDelegate flutterUndoManagerPlugin:self
68+
handleUndoWithDirection:direction];
69+
}];
70+
[undoManager endUndoGrouping];
7471
}
7572

7673
- (void)registerRedo API_AVAILABLE(ios(9.0)) {
77-
[[self undoManager] beginUndoGrouping];
78-
[[self undoManager]
79-
registerUndoWithTarget:self
80-
handler:^(id target) {
81-
// Register undo with opposite direction.
82-
[target registerUndoWithDirection:FlutterUndoRedoDirectionRedo];
83-
}];
84-
[[self undoManager] endUndoGrouping];
85-
[[self undoManager] undo];
74+
NSUndoManager* undoManager = [self undoManager];
75+
[undoManager beginUndoGrouping];
76+
[undoManager registerUndoWithTarget:self
77+
handler:^(id target) {
78+
// Register undo with opposite direction.
79+
[target registerUndoWithDirection:FlutterUndoRedoDirectionRedo];
80+
}];
81+
[undoManager endUndoGrouping];
82+
[undoManager undo];
8683
}
8784

8885
- (void)setUndoState:(NSDictionary*)dictionary API_AVAILABLE(ios(9.0)) {
89-
BOOL groupsByEvent = [self undoManager].groupsByEvent;
90-
[self undoManager].groupsByEvent = NO;
86+
NSUndoManager* undoManager = [self undoManager];
87+
BOOL groupsByEvent = undoManager.groupsByEvent;
88+
undoManager.groupsByEvent = NO;
9189
BOOL canUndo = [dictionary[kCanUndo] boolValue];
9290
BOOL canRedo = [dictionary[kCanRedo] boolValue];
9391

@@ -99,16 +97,15 @@ - (void)setUndoState:(NSDictionary*)dictionary API_AVAILABLE(ios(9.0)) {
9997
if (canRedo) {
10098
[self registerRedo];
10199
}
102-
103-
if (_viewController.engine.textInputPlugin.textInputView != nil) {
100+
UIView<UITextInput>* textInputView = [self.undoManagerDelegate.textInputPlugin textInputView];
101+
if (textInputView != nil) {
104102
// This is needed to notify the iPadOS keyboard that it needs to update the
105103
// state of the UIBarButtons. Otherwise, the state changes to NSUndoManager
106104
// will not show up until the next keystroke (or other trigger).
107-
UITextInputAssistantItem* assistantItem =
108-
_viewController.engine.textInputPlugin.textInputView.inputAssistantItem;
105+
UITextInputAssistantItem* assistantItem = textInputView.inputAssistantItem;
109106
assistantItem.leadingBarButtonGroups = assistantItem.leadingBarButtonGroups;
110107
}
111-
[self undoManager].groupsByEvent = groupsByEvent;
108+
undoManager.groupsByEvent = groupsByEvent;
112109
}
113110

114111
@end

shell/platform/darwin/ios/framework/Source/FlutterUndoManagerPluginTest.mm

Lines changed: 24 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -8,51 +8,48 @@
88
#import <XCTest/XCTest.h>
99

1010
#import "flutter/shell/platform/darwin/common/framework/Headers/FlutterMacros.h"
11-
#import "flutter/shell/platform/darwin/ios/framework/Headers/FlutterEngine.h"
12-
#import "flutter/shell/platform/darwin/ios/framework/Headers/FlutterViewController.h"
1311
#import "flutter/shell/platform/darwin/ios/framework/Source/FlutterTextInputPlugin.h"
1412

1513
FLUTTER_ASSERT_ARC
1614

17-
@interface FlutterEngine ()
18-
- (nonnull FlutterUndoManagerPlugin*)undoManagerPlugin;
19-
- (nonnull FlutterTextInputPlugin*)textInputPlugin;
15+
@interface FlutterUndoManagerDelegateForTest : NSObject <FlutterUndoManagerDelegate>
16+
@property(nonatomic, weak) UIResponder* viewController;
17+
@property(nonatomic) FlutterTextInputPlugin* textInputPlugin;
2018
@end
2119

22-
@interface FlutterUndoManagerPluginForTest : FlutterUndoManagerPlugin
23-
@property(nonatomic, assign) NSUndoManager* undoManager;
24-
@end
20+
@implementation FlutterUndoManagerDelegateForTest
2521

26-
@implementation FlutterUndoManagerPluginForTest {
22+
- (void)flutterUndoManagerPlugin:(FlutterUndoManagerPlugin*)undoManagerPlugin
23+
handleUndoWithDirection:(FlutterUndoRedoDirection)direction {
2724
}
2825
@end
2926

3027
@interface FlutterUndoManagerPluginTest : XCTestCase
31-
@property(nonatomic, strong) id engine;
32-
@property(nonatomic, strong) FlutterUndoManagerPluginForTest* undoManagerPlugin;
33-
@property(nonatomic, strong) FlutterViewController* viewController;
34-
@property(nonatomic, strong) NSUndoManager* undoManager;
28+
@property(nonatomic) id undoManagerDelegate;
29+
@property(nonatomic) FlutterUndoManagerPlugin* undoManagerPlugin;
30+
@property(nonatomic) UIResponder* viewController;
31+
@property(nonatomic) NSUndoManager* undoManager;
3532
@end
3633

37-
@implementation FlutterUndoManagerPluginTest {
38-
}
34+
@implementation FlutterUndoManagerPluginTest
3935

4036
- (void)setUp {
4137
[super setUp];
42-
self.engine = OCMClassMock([FlutterEngine class]);
43-
44-
self.undoManagerPlugin = [[FlutterUndoManagerPluginForTest alloc] initWithDelegate:self.engine];
38+
self.undoManagerDelegate = OCMClassMock([FlutterUndoManagerDelegateForTest class]);
4539

46-
self.viewController = [[FlutterViewController alloc] init];
47-
self.undoManagerPlugin.viewController = self.viewController;
40+
self.undoManagerPlugin =
41+
[[FlutterUndoManagerPlugin alloc] initWithDelegate:self.undoManagerDelegate];
4842

4943
self.undoManager = OCMClassMock([NSUndoManager class]);
50-
self.undoManagerPlugin.undoManager = self.undoManager;
44+
45+
self.viewController = OCMClassMock([UIResponder class]);
46+
OCMStub([self.viewController undoManager]).andReturn(self.undoManager);
47+
OCMStub([self.undoManagerDelegate viewController]).andReturn(self.viewController);
5148
}
5249

5350
- (void)tearDown {
5451
[self.undoManager removeAllActionsWithTarget:self.undoManagerPlugin];
55-
self.engine = nil;
52+
self.undoManagerDelegate = nil;
5653
self.viewController = nil;
5754
self.undoManager = nil;
5855
[super tearDown];
@@ -75,14 +72,14 @@ - (void)testSetUndoState {
7572
removeAllActionsCount++;
7673
});
7774
__block int delegateUndoCount = 0;
78-
OCMStub([self.engine flutterUndoManagerPlugin:[OCMArg any]
79-
handleUndoWithDirection:FlutterUndoRedoDirectionUndo])
75+
OCMStub([self.undoManagerDelegate flutterUndoManagerPlugin:[OCMArg any]
76+
handleUndoWithDirection:FlutterUndoRedoDirectionUndo])
8077
.andDo(^(NSInvocation* invocation) {
8178
delegateUndoCount++;
8279
});
8380
__block int delegateRedoCount = 0;
84-
OCMStub([self.engine flutterUndoManagerPlugin:[OCMArg any]
85-
handleUndoWithDirection:FlutterUndoRedoDirectionRedo])
81+
OCMStub([self.undoManagerDelegate flutterUndoManagerPlugin:[OCMArg any]
82+
handleUndoWithDirection:FlutterUndoRedoDirectionRedo])
8683
.andDo(^(NSInvocation* invocation) {
8784
delegateRedoCount++;
8885
});
@@ -143,14 +140,10 @@ - (void)testSetUndoState {
143140

144141
- (void)testSetUndoStateDoesInteractWithInputDelegate {
145142
// Regression test for https://github.com/flutter/flutter/issues/133424
146-
FlutterViewController* viewController = OCMPartialMock(self.viewController);
147-
self.undoManagerPlugin.viewController = self.viewController;
148-
149143
FlutterTextInputPlugin* textInputPlugin = OCMClassMock([FlutterTextInputPlugin class]);
150144
FlutterTextInputView* textInputView = OCMClassMock([FlutterTextInputView class]);
151145

152-
OCMStub([viewController engine]).andReturn(self.engine);
153-
OCMStub([self.engine textInputPlugin]).andReturn(textInputPlugin);
146+
OCMStub([self.undoManagerDelegate textInputPlugin]).andReturn(textInputPlugin);
154147
OCMStub([textInputPlugin textInputView]).andReturn(textInputView);
155148

156149
FlutterMethodCall* setUndoStateCall =

testing/ios/IosUnitTests/IosUnitTests.xcodeproj/xcshareddata/xcschemes/IosUnitTests.xcscheme

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,8 @@
2626
buildConfiguration = "Debug"
2727
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
2828
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
29-
shouldUseLaunchSchemeArgsEnv = "YES">
29+
shouldUseLaunchSchemeArgsEnv = "YES"
30+
codeCoverageEnabled = "YES">
3031
<AdditionalOptions>
3132
<AdditionalOption
3233
key = "MallocStackLogging"

0 commit comments

Comments
 (0)