From 7ca4e719eb181e74b789010ae465b1c4feb8106d Mon Sep 17 00:00:00 2001 From: Jenn Magder Date: Mon, 8 Nov 2021 20:50:22 -0800 Subject: [PATCH 1/3] Fix memory management analyzer warnings --- .../framework/Headers/FlutterCallbackCache.h | 6 +++--- .../framework/Source/FlutterAppDelegate.mm | 1 + .../Source/FlutterAppDelegateTest.mm | 16 ++++++++++++++ .../framework/Source/FlutterCallbackCache.mm | 8 +++++++ .../framework/Source/FlutterDartProject.mm | 3 ++- .../Source/FlutterEmbedderKeyResponder.mm | 7 ++++--- .../ios/framework/Source/FlutterEngine.mm | 1 + .../framework/Source/FlutterEngineGroup.mm | 7 ++++--- .../Source/FlutterEngineGroupTest.mm | 14 +++++++++++++ .../Source/FlutterKeyboardManager.mm | 8 ++++--- .../Source/FlutterObservatoryPublisher.h | 2 +- .../Source/FlutterObservatoryPublisher.mm | 1 + .../Source/FlutterPlatformViews_Internal.mm | 2 +- .../Source/FlutterTextInputPlugin.mm | 10 +++++---- .../framework/Source/FlutterViewController.mm | 21 ++++++++++++------- .../Source/FlutterViewControllerTest.mm | 15 +++++++++++++ .../Source/FlutterViewController_Internal.h | 2 +- .../ios/framework/Source/SemanticsObject.mm | 2 +- .../Source/accessibility_text_entry.h | 8 +++---- .../Source/accessibility_text_entry.mm | 9 ++++++-- .../darwin/ios/rendering_api_selection.mm | 1 + 21 files changed, 110 insertions(+), 34 deletions(-) diff --git a/shell/platform/darwin/ios/framework/Headers/FlutterCallbackCache.h b/shell/platform/darwin/ios/framework/Headers/FlutterCallbackCache.h index 079fe768dea9c..d2065586856ad 100644 --- a/shell/platform/darwin/ios/framework/Headers/FlutterCallbackCache.h +++ b/shell/platform/darwin/ios/framework/Headers/FlutterCallbackCache.h @@ -18,15 +18,15 @@ FLUTTER_DARWIN_EXPORT /** * The name of the callback. */ -@property(retain) NSString* callbackName; +@property(copy) NSString* callbackName; /** * The class name of the callback. */ -@property(retain) NSString* callbackClassName; +@property(copy) NSString* callbackClassName; /** * The library path of the callback. */ -@property(retain) NSString* callbackLibraryPath; +@property(copy) NSString* callbackLibraryPath; @end /** diff --git a/shell/platform/darwin/ios/framework/Source/FlutterAppDelegate.mm b/shell/platform/darwin/ios/framework/Source/FlutterAppDelegate.mm index 44b2800ce5818..a50924e1661ce 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterAppDelegate.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterAppDelegate.mm @@ -34,6 +34,7 @@ - (instancetype)init { - (void)dealloc { [_lifeCycleDelegate release]; [_rootFlutterViewControllerGetter release]; + [_window release]; [super dealloc]; } diff --git a/shell/platform/darwin/ios/framework/Source/FlutterAppDelegateTest.mm b/shell/platform/darwin/ios/framework/Source/FlutterAppDelegateTest.mm index c8c4aa700c91d..33b4e423ce3dd 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterAppDelegateTest.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterAppDelegateTest.mm @@ -121,6 +121,22 @@ - (void)testLaunchUrlWithFragmentNoQueryParameter { arguments:@"/custom/route#fragment"]); } +- (void)testReleasesWindowOnDealloc { + __weak UIWindow* weakWindow; + @autoreleasepool { + id mockWindow = OCMClassMock([UIWindow class]); + FlutterAppDelegate* appDelegate = [[FlutterAppDelegate alloc] init]; + appDelegate.window = mockWindow; + weakWindow = mockWindow; + XCTAssertNotNil(weakWindow); + [mockWindow stopMocking]; + mockWindow = nil; + appDelegate = nil; + } + // App delegate has released the window. + XCTAssertNil(weakWindow); +} + #pragma mark - Deep linking - (void)testUniversalLinkPushRoute { diff --git a/shell/platform/darwin/ios/framework/Source/FlutterCallbackCache.mm b/shell/platform/darwin/ios/framework/Source/FlutterCallbackCache.mm index 8c89044f72658..1aea364a58aa7 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterCallbackCache.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterCallbackCache.mm @@ -7,6 +7,14 @@ #include "flutter/lib/ui/plugins/callback_cache.h" @implementation FlutterCallbackInformation + +- (void)dealloc { + [_callbackName release]; + [_callbackClassName release]; + [_callbackLibraryPath release]; + [super dealloc]; +} + @end @implementation FlutterCallbackCache diff --git a/shell/platform/darwin/ios/framework/Source/FlutterDartProject.mm b/shell/platform/darwin/ios/framework/Source/FlutterDartProject.mm index 2d650a773645a..bf3e13368c14a 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterDartProject.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterDartProject.mm @@ -288,7 +288,8 @@ + (NSString*)domainNetworkPolicy:(NSDictionary*)appTransportSecurity { NSData* jsonData = [NSJSONSerialization dataWithJSONObject:networkConfigArray options:0 error:NULL]; - return [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding]; + [networkConfigArray release]; + return [[[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding] autorelease]; } + (bool)allowsArbitraryLoads:(NSDictionary*)appTransportSecurity { diff --git a/shell/platform/darwin/ios/framework/Source/FlutterEmbedderKeyResponder.mm b/shell/platform/darwin/ios/framework/Source/FlutterEmbedderKeyResponder.mm index 82c430093e14c..2bb10c182d84f 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterEmbedderKeyResponder.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterEmbedderKeyResponder.mm @@ -349,7 +349,7 @@ @interface FlutterEmbedderKeyResponder () * * Set by the initializer. */ -@property(nonatomic) FlutterSendKeyEvent sendEvent; +@property(nonatomic, copy, readonly) FlutterSendKeyEvent sendEvent; /** * A map of pressed keys. @@ -357,7 +357,7 @@ @interface FlutterEmbedderKeyResponder () * The keys of the dictionary are physical keys, while the values are the logical keys * of the key down event. */ -@property(nonatomic) NSMutableDictionary* pressingRecords; +@property(nonatomic, retain, readonly) NSMutableDictionary* pressingRecords; /** * A constant mask for NSEvent.modifierFlags that Flutter synchronizes with. @@ -396,7 +396,8 @@ @interface FlutterEmbedderKeyResponder () * Its values are |responseId|s, and keys are the callback that was received * along with the event. */ -@property(nonatomic) NSMutableDictionary* pendingResponses; +@property(nonatomic, retain, readonly) + NSMutableDictionary* pendingResponses; /** * Compare the last modifier flags and the current, and dispatch synthesized diff --git a/shell/platform/darwin/ios/framework/Source/FlutterEngine.mm b/shell/platform/darwin/ios/framework/Source/FlutterEngine.mm index 46a6ea6f077b8..b12dd5929193b 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterEngine.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterEngine.mm @@ -211,6 +211,7 @@ - (void)dealloc { [_registrars release]; _binaryMessenger.parent = nil; [_binaryMessenger release]; + [_isolateId release]; NSNotificationCenter* center = [NSNotificationCenter defaultCenter]; if (_flutterViewControllerWillDeallocObserver) { diff --git a/shell/platform/darwin/ios/framework/Source/FlutterEngineGroup.mm b/shell/platform/darwin/ios/framework/Source/FlutterEngineGroup.mm index 6c03558b146b9..ee6efe9cb3f20 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterEngineGroup.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterEngineGroup.mm @@ -18,9 +18,9 @@ @implementation FlutterEngineGroup { - (instancetype)initWithName:(NSString*)name project:(nullable FlutterDartProject*)project { self = [super init]; if (self) { - self.name = name; - self.engines = [[NSMutableArray alloc] init]; - self.project = project; + _name = [name copy]; + _engines = [[NSMutableArray alloc] init]; + _project = [project retain]; } return self; } @@ -30,6 +30,7 @@ - (void)dealloc { [center removeObserver:self]; [_name release]; [_engines release]; + [_project release]; [super dealloc]; } diff --git a/shell/platform/darwin/ios/framework/Source/FlutterEngineGroupTest.mm b/shell/platform/darwin/ios/framework/Source/FlutterEngineGroupTest.mm index ad2df532da8c2..a861eb4f013f2 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterEngineGroupTest.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterEngineGroupTest.mm @@ -42,4 +42,18 @@ - (void)testDeleteLastEngine { XCTAssertNotNil(spawnee); } +- (void)testReleasesProjectOnDealloc { + __weak FlutterDartProject* weakProject; + @autoreleasepool { + FlutterDartProject* mockProject = OCMClassMock([FlutterDartProject class]); + FlutterEngineGroup* group = [[FlutterEngineGroup alloc] initWithName:@"foo" + project:mockProject]; + weakProject = mockProject; + XCTAssertNotNil(weakProject); + group = nil; + mockProject = nil; + } + XCTAssertNil(weakProject); +} + @end diff --git a/shell/platform/darwin/ios/framework/Source/FlutterKeyboardManager.mm b/shell/platform/darwin/ios/framework/Source/FlutterKeyboardManager.mm index 4d8d7b94e7573..8ff7d01953ae6 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterKeyboardManager.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterKeyboardManager.mm @@ -13,12 +13,14 @@ @interface FlutterKeyboardManager () /** * The primary responders added by addPrimaryResponder. */ -@property(nonatomic) NSMutableArray>* primaryResponders; +@property(nonatomic, retain, readonly) + NSMutableArray>* primaryResponders; /** * The secondary responders added by addSecondaryResponder. */ -@property(nonatomic) NSMutableArray>* secondaryResponders; +@property(nonatomic, retain, readonly) + NSMutableArray>* secondaryResponders; - (void)dispatchToSecondaryResponders:(nonnull FlutterUIPressProxy*)press complete:(nonnull KeyEventCompleteCallback)callback @@ -84,7 +86,7 @@ - (void)handlePress:(nonnull FlutterUIPressProxy*)press NSAssert([_primaryResponders count] >= 0, @"At least one primary responder must be added."); __block auto weakSelf = [self getWeakPtr]; - __block int unreplied = [_primaryResponders count]; + __block NSUInteger unreplied = [self.primaryResponders count]; __block BOOL anyHandled = false; FlutterAsyncKeyCallback replyCallback = ^(BOOL handled) { unreplied--; diff --git a/shell/platform/darwin/ios/framework/Source/FlutterObservatoryPublisher.h b/shell/platform/darwin/ios/framework/Source/FlutterObservatoryPublisher.h index a00c17ad89245..0c3fe202c6116 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterObservatoryPublisher.h +++ b/shell/platform/darwin/ios/framework/Source/FlutterObservatoryPublisher.h @@ -14,7 +14,7 @@ - (instancetype)init NS_UNAVAILABLE; + (instancetype)new NS_UNAVAILABLE; -@property(nonatomic, readonly) NSURL* url; +@property(nonatomic, retain, readonly) NSURL* url; @end diff --git a/shell/platform/darwin/ios/framework/Source/FlutterObservatoryPublisher.mm b/shell/platform/darwin/ios/framework/Source/FlutterObservatoryPublisher.mm index c9b124ba4e264..30f03dbf5f885 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterObservatoryPublisher.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterObservatoryPublisher.mm @@ -212,6 +212,7 @@ - (instancetype)initWithEnableObservatoryPublication:(BOOL)enableObservatoryPubl if (weak.get().enableObservatoryPublication) { [[weak.get() delegate] publishServiceProtocolPort:url]; } + [url release]; } }); } diff --git a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.mm b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.mm index a6d3d03653b17..c662a078f2a16 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.mm @@ -84,7 +84,7 @@ @implementation FlutterClippingMaskView { } - (instancetype)initWithFrame:(CGRect)frame { - if ([super initWithFrame:frame]) { + if (self = [super initWithFrame:frame]) { self.backgroundColor = UIColor.clearColor; } return self; diff --git a/shell/platform/darwin/ios/framework/Source/FlutterTextInputPlugin.mm b/shell/platform/darwin/ios/framework/Source/FlutterTextInputPlugin.mm index 4a111d3aace6f..b073b7321d353 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterTextInputPlugin.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterTextInputPlugin.mm @@ -872,6 +872,8 @@ - (void)dealloc { [_autofillId release]; [_inputViewController release]; [_selectionRects release]; + [_markedTextStyle release]; + [_textContentType release]; [super dealloc]; } @@ -957,8 +959,8 @@ - (NSRange)clampSelectionFromBase:(int)selectionBase } - (NSRange)clampSelection:(NSRange)range forText:(NSString*)text { - int start = MIN(MAX(range.location, 0), text.length); - int length = MIN(range.length, text.length - start); + NSUInteger start = MIN(MAX(range.location, 0), text.length); + NSUInteger length = MIN(range.length, text.length - start); return NSMakeRange(start, length); } @@ -1118,8 +1120,8 @@ - (NSString*)textInRange:(UITextRange*)range { NSRange textRange = ((FlutterTextRange*)range).range; NSAssert(textRange.location != NSNotFound, @"Expected a valid text range."); // Sanitize the range to prevent going out of bounds. - int location = MIN(textRange.location, self.text.length); - int length = MIN(self.text.length - location, textRange.length); + NSUInteger location = MIN(textRange.location, self.text.length); + NSUInteger length = MIN(self.text.length - location, textRange.length); NSRange safeRange = NSMakeRange(location, length); return [self.text substringWithRange:safeRange]; } diff --git a/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm b/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm index adc0115d37ed5..081e7a36aa83a 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm @@ -671,21 +671,27 @@ - (void)viewDidLoad { } - (void)addInternalPlugins { - [self.keyboardManager release]; - self.keyboardManager = [[FlutterKeyboardManager alloc] init]; + FlutterKeyboardManager* keyboardManager = [[FlutterKeyboardManager alloc] init]; + self.keyboardManager = keyboardManager; + [keyboardManager release]; + fml::WeakPtr weakSelf = [self getWeakPtr]; FlutterSendKeyEvent sendEvent = ^(const FlutterKeyEvent& event, FlutterKeyEventCallback callback, void* userData) { - [_engine.get() sendKeyEvent:event callback:callback userData:userData]; + [weakSelf.get()->_engine.get() sendKeyEvent:event callback:callback userData:userData]; }; [self.keyboardManager addPrimaryResponder:[[FlutterEmbedderKeyResponder alloc] initWithSendEvent:sendEvent]]; - [self.keyboardManager addPrimaryResponder:[[FlutterChannelKeyResponder alloc] - initWithChannel:self.engine.keyEventChannel]]; - [self.keyboardManager addSecondaryResponder:self.engine.textInputPlugin]; + FlutterChannelKeyResponder* responder = + [[FlutterChannelKeyResponder alloc] initWithChannel:self.engine.keyEventChannel]; + [self.keyboardManager addPrimaryResponder:responder]; + [responder release]; + FlutterTextInputPlugin* textInputPlugin = self.engine.textInputPlugin; + if (textInputPlugin != nil) { + [self.keyboardManager addSecondaryResponder:self.engine.textInputPlugin]; + } } - (void)removeInternalPlugins { - [self.keyboardManager release]; self.keyboardManager = nil; } @@ -1729,6 +1735,7 @@ - (void)scrollEvent:(UIPanGestureRecognizer*)recognizer API_AVAILABLE(ios(13.4)) - (void)encodeRestorableStateWithCoder:(NSCoder*)coder { NSData* restorationData = [[_engine.get() restorationPlugin] restorationData]; [coder encodeDataObject:restorationData]; + [super encodeRestorableStateWithCoder:coder]; } - (void)decodeRestorableStateWithCoder:(NSCoder*)coder { diff --git a/shell/platform/darwin/ios/framework/Source/FlutterViewControllerTest.mm b/shell/platform/darwin/ios/framework/Source/FlutterViewControllerTest.mm index 84abb4bb13dbe..2c462e479c56d 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterViewControllerTest.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterViewControllerTest.mm @@ -760,6 +760,21 @@ - (void)testWillDeallocNotification { [self waitForExpectations:@[ expectation ] timeout:1.0]; } +- (void)testReleasesKeyboardManagerOnDealloc { + __weak FlutterKeyboardManager* weakKeyboardManager = nil; + @autoreleasepool { + FlutterViewController* viewController = [[FlutterViewController alloc] init]; + + [viewController addInternalPlugins]; + weakKeyboardManager = viewController.keyboardManager; + XCTAssertNotNil(weakKeyboardManager); + [viewController deregisterNotifications]; + viewController = nil; + } + // View controller has released the keyboard manager. + XCTAssertNil(weakKeyboardManager); +} + - (void)testDoesntLoadViewInInit { FlutterDartProject* project = [[FlutterDartProject alloc] init]; FlutterEngine* engine = [[FlutterEngine alloc] initWithName:@"foobar" project:project]; diff --git a/shell/platform/darwin/ios/framework/Source/FlutterViewController_Internal.h b/shell/platform/darwin/ios/framework/Source/FlutterViewController_Internal.h index 16febb55f99ac..6629d8809a5a0 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterViewController_Internal.h +++ b/shell/platform/darwin/ios/framework/Source/FlutterViewController_Internal.h @@ -31,7 +31,7 @@ extern NSNotificationName const FlutterViewControllerShowHomeIndicator; @property(nonatomic, readonly) BOOL isPresentingViewController; @property(nonatomic, readonly) BOOL isVoiceOverRunning; -@property(nonatomic) FlutterKeyboardManager* keyboardManager; +@property(nonatomic, strong) FlutterKeyboardManager* keyboardManager; - (fml::WeakPtr)getWeakPtr; - (std::shared_ptr&)platformViewsController; - (FlutterRestorationPlugin*)restorationPlugin; diff --git a/shell/platform/darwin/ios/framework/Source/SemanticsObject.mm b/shell/platform/darwin/ios/framework/Source/SemanticsObject.mm index f627f2de9e81c..c7497a9687eaa 100644 --- a/shell/platform/darwin/ios/framework/Source/SemanticsObject.mm +++ b/shell/platform/darwin/ios/framework/Source/SemanticsObject.mm @@ -433,7 +433,7 @@ - (NSAttributedString*)createAttributedStringFromString:(NSString*)string } } } - return attributedString; + return [attributedString autorelease]; } #pragma mark - UIAccessibility overrides diff --git a/shell/platform/darwin/ios/framework/Source/accessibility_text_entry.h b/shell/platform/darwin/ios/framework/Source/accessibility_text_entry.h index 163346d7b04dd..9df47186ccf73 100644 --- a/shell/platform/darwin/ios/framework/Source/accessibility_text_entry.h +++ b/shell/platform/darwin/ios/framework/Source/accessibility_text_entry.h @@ -14,10 +14,10 @@ @interface FlutterInactiveTextInput : UIView @property(nonatomic, copy) NSString* text; -@property(nonatomic, readonly) NSMutableString* markedText; -@property(readwrite, copy) UITextRange* selectedTextRange; -@property(nonatomic, strong) UITextRange* markedTextRange; -@property(nonatomic, copy) NSDictionary* markedTextStyle; +@property(nonatomic, copy, readonly) NSMutableString* markedText; +@property(copy) UITextRange* selectedTextRange; +@property(nonatomic, strong, readonly) UITextRange* markedTextRange; +@property(nonatomic, copy) NSDictionary* markedTextStyle; @property(nonatomic, assign) id inputDelegate; @end diff --git a/shell/platform/darwin/ios/framework/Source/accessibility_text_entry.mm b/shell/platform/darwin/ios/framework/Source/accessibility_text_entry.mm index 2b6b52289b43d..2bbddf3f751b0 100644 --- a/shell/platform/darwin/ios/framework/Source/accessibility_text_entry.mm +++ b/shell/platform/darwin/ios/framework/Source/accessibility_text_entry.mm @@ -16,8 +16,13 @@ @implementation FlutterInactiveTextInput { @synthesize beginningOfDocument = _beginningOfDocument; @synthesize endOfDocument = _endOfDocument; -- (instancetype)init { - return [super init]; +- (void)dealloc { + [_text release]; + [_markedText release]; + [_markedTextRange release]; + [_selectedTextRange release]; + [_markedTextStyle release]; + [super dealloc]; } - (BOOL)hasText { diff --git a/shell/platform/darwin/ios/rendering_api_selection.mm b/shell/platform/darwin/ios/rendering_api_selection.mm index b2472df89edf7..b713e94ff527b 100644 --- a/shell/platform/darwin/ios/rendering_api_selection.mm +++ b/shell/platform/darwin/ios/rendering_api_selection.mm @@ -22,6 +22,7 @@ bool ShouldUseMetalRenderer() { if (@available(iOS METAL_IOS_VERSION_BASELINE, *)) { auto device = MTLCreateSystemDefaultDevice(); ios_version_supports_metal = [device supportsFeatureSet:MTLFeatureSet_iOS_GPUFamily1_v3]; + [device release]; } return ios_version_supports_metal; } From 777d088758ce46e44282f0556c0f059e0e74440e Mon Sep 17 00:00:00 2001 From: Jenn Magder Date: Wed, 10 Nov 2021 14:55:31 -0800 Subject: [PATCH 2/3] Review edits --- .../darwin/common/framework/Source/FlutterCodecs.mm | 8 ++++---- .../ios/framework/Source/FlutterDartProject.mm | 3 +-- .../ios/framework/Source/FlutterEngineGroup.mm | 4 ++-- .../framework/Source/FlutterObservatoryPublisher.mm | 5 ++--- .../ios/framework/Source/FlutterTextInputPlugin.mm | 8 ++++---- .../ios/framework/Source/FlutterUmbrellaImport.m | 2 ++ .../ios/framework/Source/FlutterViewController.mm | 13 +++++-------- .../Source/FlutterViewController_Internal.h | 2 +- .../darwin/ios/framework/Source/SemanticsObject.mm | 8 ++++---- 9 files changed, 25 insertions(+), 28 deletions(-) diff --git a/shell/platform/darwin/common/framework/Source/FlutterCodecs.mm b/shell/platform/darwin/common/framework/Source/FlutterCodecs.mm index 27bbbce5c9435..d811602b78be5 100644 --- a/shell/platform/darwin/common/framework/Source/FlutterCodecs.mm +++ b/shell/platform/darwin/common/framework/Source/FlutterCodecs.mm @@ -10,7 +10,7 @@ @implementation FlutterBinaryCodec + (instancetype)sharedInstance { static id _sharedInstance = nil; if (!_sharedInstance) { - _sharedInstance = [FlutterBinaryCodec new]; + _sharedInstance = [[FlutterBinaryCodec alloc] init]; } return _sharedInstance; } @@ -29,7 +29,7 @@ @implementation FlutterStringCodec + (instancetype)sharedInstance { static id _sharedInstance = nil; if (!_sharedInstance) { - _sharedInstance = [FlutterStringCodec new]; + _sharedInstance = [[FlutterStringCodec alloc] init]; } return _sharedInstance; } @@ -54,7 +54,7 @@ @implementation FlutterJSONMessageCodec + (instancetype)sharedInstance { static id _sharedInstance = nil; if (!_sharedInstance) { - _sharedInstance = [FlutterJSONMessageCodec new]; + _sharedInstance = [[FlutterJSONMessageCodec alloc] init]; } return _sharedInstance; } @@ -109,7 +109,7 @@ @implementation FlutterJSONMethodCodec + (instancetype)sharedInstance { static id _sharedInstance = nil; if (!_sharedInstance) { - _sharedInstance = [FlutterJSONMethodCodec new]; + _sharedInstance = [[FlutterJSONMethodCodec alloc] init]; } return _sharedInstance; } diff --git a/shell/platform/darwin/ios/framework/Source/FlutterDartProject.mm b/shell/platform/darwin/ios/framework/Source/FlutterDartProject.mm index bf3e13368c14a..dbf656a38f513 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterDartProject.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterDartProject.mm @@ -273,7 +273,7 @@ + (NSString*)domainNetworkPolicy:(NSDictionary*)appTransportSecurity { if (exceptionDomains == nil) { return @""; } - NSMutableArray* networkConfigArray = [[NSMutableArray alloc] init]; + NSMutableArray* networkConfigArray = [[[NSMutableArray alloc] init] autorelease]; for (NSString* domain in exceptionDomains) { NSDictionary* domainConfiguration = [exceptionDomains objectForKey:domain]; // Default value is false. @@ -288,7 +288,6 @@ + (NSString*)domainNetworkPolicy:(NSDictionary*)appTransportSecurity { NSData* jsonData = [NSJSONSerialization dataWithJSONObject:networkConfigArray options:0 error:NULL]; - [networkConfigArray release]; return [[[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding] autorelease]; } diff --git a/shell/platform/darwin/ios/framework/Source/FlutterEngineGroup.mm b/shell/platform/darwin/ios/framework/Source/FlutterEngineGroup.mm index ee6efe9cb3f20..741c98f605553 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterEngineGroup.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterEngineGroup.mm @@ -7,8 +7,8 @@ @interface FlutterEngineGroup () @property(nonatomic, copy) NSString* name; -@property(nonatomic, strong) NSMutableArray* engines; -@property(nonatomic, strong) FlutterDartProject* project; +@property(nonatomic, retain) NSMutableArray* engines; +@property(nonatomic, retain) FlutterDartProject* project; @end @implementation FlutterEngineGroup { diff --git a/shell/platform/darwin/ios/framework/Source/FlutterObservatoryPublisher.mm b/shell/platform/darwin/ios/framework/Source/FlutterObservatoryPublisher.mm index 30f03dbf5f885..592f5b71a85bc 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterObservatoryPublisher.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterObservatoryPublisher.mm @@ -206,13 +206,12 @@ - (instancetype)initWithEnableObservatoryPublication:(BOOL)enableObservatoryPubl // uri comes in as something like 'http://127.0.0.1:XXXXX/' where XXXXX is the port // number. if (weak) { - NSURL* url = - [[NSURL alloc] initWithString:[NSString stringWithUTF8String:uri.c_str()]]; + NSURL* url = [[[NSURL alloc] + initWithString:[NSString stringWithUTF8String:uri.c_str()]] autorelease]; weak.get().url = url; if (weak.get().enableObservatoryPublication) { [[weak.get() delegate] publishServiceProtocolPort:url]; } - [url release]; } }); } diff --git a/shell/platform/darwin/ios/framework/Source/FlutterTextInputPlugin.mm b/shell/platform/darwin/ios/framework/Source/FlutterTextInputPlugin.mm index b073b7321d353..9ade729d1a4f1 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterTextInputPlugin.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterTextInputPlugin.mm @@ -650,7 +650,7 @@ @implementation FlutterTextPlaceholder // currently only support UITextFields, and password saving only supports // UITextFields and UITextViews, as of iOS 13.5. @interface FlutterSecureTextInputView : FlutterTextInputView -@property(nonatomic, strong, readonly) UITextField* textField; +@property(nonatomic, retain, readonly) UITextField* textField; @end @implementation FlutterSecureTextInputView { @@ -693,7 +693,7 @@ @interface FlutterTextInputView () @property(nonatomic, assign) CGRect markedRect; @property(nonatomic) BOOL isVisibleToAutofill; @property(nonatomic, assign) BOOL accessibilityEnabled; -@property(nonatomic, strong) UITextInteraction* textInteraction API_AVAILABLE(ios(13.0)); +@property(nonatomic, retain) UITextInteraction* textInteraction API_AVAILABLE(ios(13.0)); - (void)setEditableTransform:(NSArray*)matrix; @end @@ -1920,8 +1920,8 @@ @interface FlutterTextInputPlugin () // The current password-autofillable input fields that have yet to be saved. @property(nonatomic, readonly) NSMutableDictionary* autofillContext; -@property(nonatomic, strong) FlutterTextInputView* activeView; -@property(nonatomic, strong) FlutterTextInputViewAccessibilityHider* inputHider; +@property(nonatomic, retain) FlutterTextInputView* activeView; +@property(nonatomic, retain) FlutterTextInputViewAccessibilityHider* inputHider; @property(nonatomic, readonly) id viewResponder; @end diff --git a/shell/platform/darwin/ios/framework/Source/FlutterUmbrellaImport.m b/shell/platform/darwin/ios/framework/Source/FlutterUmbrellaImport.m index ea73b2d1e050f..849a05e5a052a 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterUmbrellaImport.m +++ b/shell/platform/darwin/ios/framework/Source/FlutterUmbrellaImport.m @@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +// FLUTTER_NOLINT: https://github.com/flutter/flutter/issues/93360 + // The only point of this file is to ensure that the Flutter framework umbrella header can be // cleanly imported from an Objective-C translation unit. The target that uses this file copies the // headers to a path that simulates how users would actually import the framework outside of the diff --git a/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm b/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm index 081e7a36aa83a..3e687d4633bc0 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm @@ -73,7 +73,7 @@ @interface FlutterViewController () weakSelf = [self getWeakPtr]; FlutterSendKeyEvent sendEvent = ^(const FlutterKeyEvent& event, FlutterKeyEventCallback callback, void* userData) { @@ -681,13 +679,12 @@ - (void)addInternalPlugins { }; [self.keyboardManager addPrimaryResponder:[[FlutterEmbedderKeyResponder alloc] initWithSendEvent:sendEvent]]; - FlutterChannelKeyResponder* responder = - [[FlutterChannelKeyResponder alloc] initWithChannel:self.engine.keyEventChannel]; + FlutterChannelKeyResponder* responder = [[[FlutterChannelKeyResponder alloc] + initWithChannel:self.engine.keyEventChannel] autorelease]; [self.keyboardManager addPrimaryResponder:responder]; - [responder release]; FlutterTextInputPlugin* textInputPlugin = self.engine.textInputPlugin; if (textInputPlugin != nil) { - [self.keyboardManager addSecondaryResponder:self.engine.textInputPlugin]; + [self.keyboardManager addSecondaryResponder:textInputPlugin]; } } diff --git a/shell/platform/darwin/ios/framework/Source/FlutterViewController_Internal.h b/shell/platform/darwin/ios/framework/Source/FlutterViewController_Internal.h index 6629d8809a5a0..9e069b467828a 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterViewController_Internal.h +++ b/shell/platform/darwin/ios/framework/Source/FlutterViewController_Internal.h @@ -31,7 +31,7 @@ extern NSNotificationName const FlutterViewControllerShowHomeIndicator; @property(nonatomic, readonly) BOOL isPresentingViewController; @property(nonatomic, readonly) BOOL isVoiceOverRunning; -@property(nonatomic, strong) FlutterKeyboardManager* keyboardManager; +@property(nonatomic, retain) FlutterKeyboardManager* keyboardManager; - (fml::WeakPtr)getWeakPtr; - (std::shared_ptr&)platformViewsController; - (FlutterRestorationPlugin*)restorationPlugin; diff --git a/shell/platform/darwin/ios/framework/Source/SemanticsObject.mm b/shell/platform/darwin/ios/framework/Source/SemanticsObject.mm index c7497a9687eaa..dfdf02a0056f8 100644 --- a/shell/platform/darwin/ios/framework/Source/SemanticsObject.mm +++ b/shell/platform/darwin/ios/framework/Source/SemanticsObject.mm @@ -146,7 +146,7 @@ - (UIAccessibilityTraits)accessibilityTraits { @end // FlutterSwitchSemanticsObject @interface FlutterScrollableSemanticsObject () -@property(nonatomic, strong) FlutterSemanticsScrollView* scrollView; +@property(nonatomic, retain) FlutterSemanticsScrollView* scrollView; @end @implementation FlutterScrollableSemanticsObject { @@ -409,7 +409,7 @@ - (NSAttributedString*)createAttributedStringFromString:(NSString*)string withAttributes: (const flutter::StringAttributes&)attributes { NSMutableAttributedString* attributedString = - [[NSMutableAttributedString alloc] initWithString:string]; + [[[NSMutableAttributedString alloc] initWithString:string] autorelease]; for (const auto& attribute : attributes) { NSRange range = NSMakeRange(attribute->start, attribute->end - attribute->start); switch (attribute->type) { @@ -433,7 +433,7 @@ - (NSAttributedString*)createAttributedStringFromString:(NSString*)string } } } - return [attributedString autorelease]; + return attributedString; } #pragma mark - UIAccessibility overrides @@ -749,7 +749,7 @@ - (UIAccessibilityTraits)accessibilityTraits { @end @interface FlutterPlatformViewSemanticsContainer () -@property(nonatomic, strong) UIView* platformView; +@property(nonatomic, retain) UIView* platformView; @end @implementation FlutterPlatformViewSemanticsContainer From 3087cdc1c73a3fd7d0022914a86d15a56e724f99 Mon Sep 17 00:00:00 2001 From: Jenn Magder Date: Wed, 10 Nov 2021 15:35:14 -0800 Subject: [PATCH 3/3] Fix a few more releases exposed by switching from strong to retain --- .../darwin/ios/framework/Source/FlutterTextInputPlugin.mm | 1 + .../darwin/ios/framework/Source/FlutterViewController.mm | 2 ++ 2 files changed, 3 insertions(+) diff --git a/shell/platform/darwin/ios/framework/Source/FlutterTextInputPlugin.mm b/shell/platform/darwin/ios/framework/Source/FlutterTextInputPlugin.mm index 9ade729d1a4f1..884f636313b9e 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterTextInputPlugin.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterTextInputPlugin.mm @@ -874,6 +874,7 @@ - (void)dealloc { [_selectionRects release]; [_markedTextStyle release]; [_textContentType release]; + [_textInteraction release]; [super dealloc]; } diff --git a/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm b/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm index 3e687d4633bc0..f69bce6e3906a 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm @@ -789,6 +789,8 @@ - (void)deregisterNotifications { - (void)dealloc { [self removeInternalPlugins]; [self deregisterNotifications]; + + [_displayLink release]; [super dealloc]; }