Migrate FlutterView, FlutterPlatformViews, FlutterOverlayView to ARC (#52535)
Smart pointers support ARC as of
https://github.com/flutter/engine/pull/47612, and the unit tests were
migrated in https://github.com/flutter/engine/pull/48162.
Migrate `FlutterView`, `FlutterPlatformViews`, and `FlutterOverlayView`
from MRC to ARC.
Part of https://github.com/flutter/flutter/issues/137801.
diff --git a/shell/platform/darwin/ios/BUILD.gn b/shell/platform/darwin/ios/BUILD.gn
index 2ddfd93..e6b6c9f 100644
--- a/shell/platform/darwin/ios/BUILD.gn
+++ b/shell/platform/darwin/ios/BUILD.gn
@@ -73,6 +73,11 @@
"framework/Source/FlutterKeyboardManager.mm",
"framework/Source/FlutterMetalLayer.h",
"framework/Source/FlutterMetalLayer.mm",
+ "framework/Source/FlutterOverlayView.h",
+ "framework/Source/FlutterOverlayView.mm",
+ "framework/Source/FlutterPlatformViews.mm",
+ "framework/Source/FlutterPlatformViews_Internal.h",
+ "framework/Source/FlutterPlatformViews_Internal.mm",
"framework/Source/FlutterRestorationPlugin.h",
"framework/Source/FlutterRestorationPlugin.mm",
"framework/Source/FlutterSpellCheckPlugin.h",
@@ -87,6 +92,9 @@
"framework/Source/FlutterUndoManagerDelegate.h",
"framework/Source/FlutterUndoManagerPlugin.h",
"framework/Source/FlutterUndoManagerPlugin.mm",
+ "framework/Source/FlutterView.h",
+ "framework/Source/FlutterView.mm",
+ "framework/Source/FlutterViewResponder.h",
"framework/Source/KeyCodeMap.g.mm",
"framework/Source/KeyCodeMap_Internal.h",
"framework/Source/UIViewController+FlutterScreenAndSceneIfLoaded.h",
@@ -160,18 +168,11 @@
"framework/Source/FlutterEngineGroup.mm",
"framework/Source/FlutterEngine_Internal.h",
"framework/Source/FlutterHeadlessDartRunner.mm",
- "framework/Source/FlutterOverlayView.h",
- "framework/Source/FlutterOverlayView.mm",
"framework/Source/FlutterPlatformPlugin.h",
"framework/Source/FlutterPlatformPlugin.mm",
- "framework/Source/FlutterPlatformViews.mm",
- "framework/Source/FlutterPlatformViews_Internal.h",
- "framework/Source/FlutterPlatformViews_Internal.mm",
"framework/Source/FlutterPluginAppLifeCycleDelegate.mm",
"framework/Source/FlutterSemanticsScrollView.h",
"framework/Source/FlutterSemanticsScrollView.mm",
- "framework/Source/FlutterView.h",
- "framework/Source/FlutterView.mm",
"framework/Source/FlutterViewController.mm",
"framework/Source/FlutterViewController_Internal.h",
"framework/Source/SemanticsObject.h",
diff --git a/shell/platform/darwin/ios/framework/Source/FlutterOverlayView.mm b/shell/platform/darwin/ios/framework/Source/FlutterOverlayView.mm
index dc29cd8..2e98396 100644
--- a/shell/platform/darwin/ios/framework/Source/FlutterOverlayView.mm
+++ b/shell/platform/darwin/ios/framework/Source/FlutterOverlayView.mm
@@ -9,6 +9,8 @@
#import "flutter/shell/platform/darwin/ios/framework/Source/FlutterView.h"
#include "fml/platform/darwin/cf_utils.h"
+FLUTTER_ASSERT_ARC
+
// This is mostly a duplication of FlutterView.
// TODO(amirh): once GL support is in evaluate if we can merge this with FlutterView.
@implementation FlutterOverlayView {
diff --git a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm
index 41295f2..46aafd8 100644
--- a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm
+++ b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm
@@ -11,6 +11,8 @@
#import "flutter/shell/platform/darwin/ios/framework/Source/FlutterView.h"
#import "flutter/shell/platform/darwin/ios/ios_surface.h"
+FLUTTER_ASSERT_ARC
+
@implementation UIView (FirstResponder)
- (BOOL)flt_hasFirstResponderInViewHierarchySubtree {
if (self.isFirstResponder) {
@@ -91,7 +93,7 @@
overlay_view.reset([[FlutterOverlayView alloc] init]);
overlay_view_wrapper.reset([[FlutterOverlayView alloc] init]);
- auto ca_layer = fml::scoped_nsobject<CALayer>{[[overlay_view.get() layer] retain]};
+ auto ca_layer = fml::scoped_nsobject<CALayer>{[overlay_view.get() layer]};
std::unique_ptr<IOSSurface> ios_surface = IOSSurface::Create(ios_context, ca_layer);
std::unique_ptr<Surface> surface = ios_surface->CreateGPUSurface();
@@ -105,7 +107,7 @@
overlay_view_wrapper.reset([[FlutterOverlayView alloc] initWithContentsScale:screenScale
pixelFormat:pixel_format]);
- auto ca_layer = fml::scoped_nsobject<CALayer>{[[overlay_view.get() layer] retain]};
+ auto ca_layer = fml::scoped_nsobject<CALayer>{[overlay_view.get() layer]};
std::unique_ptr<IOSSurface> ios_surface = IOSSurface::Create(ios_context, ca_layer);
std::unique_ptr<Surface> surface = ios_surface->CreateGPUSurface(gr_context);
@@ -159,12 +161,12 @@
}
void FlutterPlatformViewsController::SetFlutterView(UIView* flutter_view) {
- flutter_view_.reset([flutter_view retain]);
+ flutter_view_.reset(flutter_view);
}
void FlutterPlatformViewsController::SetFlutterViewController(
UIViewController<FlutterViewResponder>* flutter_view_controller) {
- flutter_view_controller_.reset([flutter_view_controller retain]);
+ flutter_view_controller_.reset(flutter_view_controller);
}
UIViewController<FlutterViewResponder>* FlutterPlatformViewsController::getFlutterViewController() {
@@ -231,21 +233,19 @@
// Set a unique view identifier, so the platform view can be identified in unit tests.
platform_view.accessibilityIdentifier =
[NSString stringWithFormat:@"platform_view[%lld]", viewId];
- views_[viewId] = fml::scoped_nsobject<NSObject<FlutterPlatformView>>([embedded_view retain]);
+ views_[viewId] = fml::scoped_nsobject<NSObject<FlutterPlatformView>>(embedded_view);
- FlutterTouchInterceptingView* touch_interceptor = [[[FlutterTouchInterceptingView alloc]
+ FlutterTouchInterceptingView* touch_interceptor = [[FlutterTouchInterceptingView alloc]
initWithEmbeddedView:platform_view
platformViewsController:GetWeakPtr()
- gestureRecognizersBlockingPolicy:gesture_recognizers_blocking_policies_[viewType]]
- autorelease];
+ gestureRecognizersBlockingPolicy:gesture_recognizers_blocking_policies_[viewType]];
touch_interceptors_[viewId] =
- fml::scoped_nsobject<FlutterTouchInterceptingView>([touch_interceptor retain]);
+ fml::scoped_nsobject<FlutterTouchInterceptingView>(touch_interceptor);
- ChildClippingView* clipping_view =
- [[[ChildClippingView alloc] initWithFrame:CGRectZero] autorelease];
+ ChildClippingView* clipping_view = [[ChildClippingView alloc] initWithFrame:CGRectZero];
[clipping_view addSubview:touch_interceptor];
- root_views_[viewId] = fml::scoped_nsobject<UIView>([clipping_view retain]);
+ root_views_[viewId] = fml::scoped_nsobject<UIView>(clipping_view);
result(nil);
}
@@ -307,8 +307,7 @@
FlutterPlatformViewGestureRecognizersBlockingPolicy gestureRecognizerBlockingPolicy) {
std::string idString([factoryId UTF8String]);
FML_CHECK(factories_.count(idString) == 0);
- factories_[idString] =
- fml::scoped_nsobject<NSObject<FlutterPlatformViewFactory>>([factory retain]);
+ factories_[idString] = fml::scoped_nsobject<NSObject<FlutterPlatformViewFactory>>(factory);
gesture_recognizers_blocking_policies_[idString] = gestureRecognizerBlockingPolicy;
}
@@ -417,7 +416,7 @@
long FlutterPlatformViewsController::FindFirstResponderPlatformViewId() {
for (auto const& [id, root_view] : root_views_) {
- if ((UIView*)(root_view.get()).flt_hasFirstResponderInViewHierarchySubtree) {
+ if (((UIView*)root_view.get()).flt_hasFirstResponderInViewHierarchySubtree) {
return id;
}
}
@@ -460,7 +459,7 @@
ChildClippingView* clipView = (ChildClippingView*)embedded_view.superview;
SkMatrix transformMatrix;
- NSMutableArray* blurFilters = [[[NSMutableArray alloc] init] autorelease];
+ NSMutableArray* blurFilters = [[NSMutableArray alloc] init];
FML_DCHECK(!clipView.maskView ||
[clipView.maskView isKindOfClass:[FlutterClippingMaskView class]]);
if (clipView.maskView) {
@@ -530,12 +529,11 @@
// is not supported in Quartz's gaussianBlur CAFilter, so it is not used
// to blur the PlatformView.
CGFloat blurRadius = (*iter)->GetFilterMutation().GetFilter().asBlur()->sigma_x();
- UIVisualEffectView* visualEffectView = [[[UIVisualEffectView alloc]
- initWithEffect:[UIBlurEffect effectWithStyle:UIBlurEffectStyleLight]] autorelease];
- PlatformViewFilter* filter =
- [[[PlatformViewFilter alloc] initWithFrame:frameInClipView
- blurRadius:blurRadius
- visualEffectView:visualEffectView] autorelease];
+ UIVisualEffectView* visualEffectView = [[UIVisualEffectView alloc]
+ initWithEffect:[UIBlurEffect effectWithStyle:UIBlurEffectStyleLight]];
+ PlatformViewFilter* filter = [[PlatformViewFilter alloc] initWithFrame:frameInClipView
+ blurRadius:blurRadius
+ visualEffectView:visualEffectView];
if (!filter) {
canApplyBlurBackdrop = NO;
} else {
@@ -950,11 +948,13 @@
// Indicates that if the `DelayingGestureRecognizer`'s state should be set to
// `UIGestureRecognizerStateEnded` during next `touchesEnded` call.
-@property(nonatomic) bool shouldEndInNextTouchesEnded;
+@property(nonatomic) BOOL shouldEndInNextTouchesEnded;
// Indicates that the `DelayingGestureRecognizer`'s `touchesEnded` has been invoked without
// setting the state to `UIGestureRecognizerStateEnded`.
-@property(nonatomic) bool touchedEndedWithoutBlocking;
+@property(nonatomic) BOOL touchedEndedWithoutBlocking;
+
+@property(nonatomic, readonly) UIGestureRecognizer* forwardingRecognizer;
- (instancetype)initWithTarget:(id)target
action:(SEL)action
@@ -977,11 +977,13 @@
(fml::WeakPtr<flutter::FlutterPlatformViewsController>)platformViewsController;
@end
-@implementation FlutterTouchInterceptingView {
- fml::scoped_nsobject<DelayingGestureRecognizer> _delayingRecognizer;
- FlutterPlatformViewGestureRecognizersBlockingPolicy _blockingPolicy;
- UIView* _embeddedView;
-}
+@interface FlutterTouchInterceptingView ()
+@property(nonatomic, weak, readonly) UIView* embeddedView;
+@property(nonatomic, readonly) DelayingGestureRecognizer* delayingRecognizer;
+@property(nonatomic, readonly) FlutterPlatformViewGestureRecognizersBlockingPolicy blockingPolicy;
+@end
+
+@implementation FlutterTouchInterceptingView
- (instancetype)initWithEmbeddedView:(UIView*)embeddedView
platformViewsController:
(fml::WeakPtr<flutter::FlutterPlatformViewsController>)platformViewsController
@@ -996,47 +998,42 @@
[self addSubview:embeddedView];
- ForwardingGestureRecognizer* forwardingRecognizer = [[[ForwardingGestureRecognizer alloc]
- initWithTarget:self
- platformViewsController:std::move(platformViewsController)] autorelease];
+ ForwardingGestureRecognizer* forwardingRecognizer =
+ [[ForwardingGestureRecognizer alloc] initWithTarget:self
+ platformViewsController:platformViewsController];
- _delayingRecognizer.reset([[DelayingGestureRecognizer alloc]
- initWithTarget:self
- action:nil
- forwardingRecognizer:forwardingRecognizer]);
+ _delayingRecognizer = [[DelayingGestureRecognizer alloc] initWithTarget:self
+ action:nil
+ forwardingRecognizer:forwardingRecognizer];
_blockingPolicy = blockingPolicy;
- [self addGestureRecognizer:_delayingRecognizer.get()];
+ [self addGestureRecognizer:_delayingRecognizer];
[self addGestureRecognizer:forwardingRecognizer];
}
return self;
}
-- (UIView*)embeddedView {
- return [[_embeddedView retain] autorelease];
-}
-
- (void)releaseGesture {
- _delayingRecognizer.get().state = UIGestureRecognizerStateFailed;
+ self.delayingRecognizer.state = UIGestureRecognizerStateFailed;
}
- (void)blockGesture {
switch (_blockingPolicy) {
case FlutterPlatformViewGestureRecognizersBlockingPolicyEager:
// We block all other gesture recognizers immediately in this policy.
- _delayingRecognizer.get().state = UIGestureRecognizerStateEnded;
+ self.delayingRecognizer.state = UIGestureRecognizerStateEnded;
break;
case FlutterPlatformViewGestureRecognizersBlockingPolicyWaitUntilTouchesEnded:
- if (_delayingRecognizer.get().touchedEndedWithoutBlocking) {
+ if (self.delayingRecognizer.touchedEndedWithoutBlocking) {
// If touchesEnded of the `DelayingGesureRecognizer` has been already invoked,
// we want to set the state of the `DelayingGesureRecognizer` to
// `UIGestureRecognizerStateEnded` as soon as possible.
- _delayingRecognizer.get().state = UIGestureRecognizerStateEnded;
+ self.delayingRecognizer.state = UIGestureRecognizerStateEnded;
} else {
// If touchesEnded of the `DelayingGesureRecognizer` has not been invoked,
// We will set a flag to notify the `DelayingGesureRecognizer` to set the state to
// `UIGestureRecognizerStateEnded` when touchesEnded is called.
- _delayingRecognizer.get().shouldEndInNextTouchesEnded = YES;
+ self.delayingRecognizer.shouldEndInNextTouchesEnded = YES;
}
break;
default:
@@ -1060,19 +1057,12 @@
}
- (id)accessibilityContainer {
- return _flutterAccessibilityContainer;
-}
-
-- (void)dealloc {
- [_flutterAccessibilityContainer release];
- [super dealloc];
+ return self.flutterAccessibilityContainer;
}
@end
-@implementation DelayingGestureRecognizer {
- fml::scoped_nsobject<UIGestureRecognizer> _forwardingRecognizer;
-}
+@implementation DelayingGestureRecognizer
- (instancetype)initWithTarget:(id)target
action:(SEL)action
@@ -1082,9 +1072,9 @@
self.delaysTouchesBegan = YES;
self.delaysTouchesEnded = YES;
self.delegate = self;
- self.shouldEndInNextTouchesEnded = NO;
- self.touchedEndedWithoutBlocking = NO;
- _forwardingRecognizer.reset([forwardingRecognizer retain]);
+ _shouldEndInNextTouchesEnded = NO;
+ _touchedEndedWithoutBlocking = NO;
+ _forwardingRecognizer = forwardingRecognizer;
}
return self;
}
@@ -1093,7 +1083,7 @@
shouldBeRequiredToFailByGestureRecognizer:(UIGestureRecognizer*)otherGestureRecognizer {
// The forwarding gesture recognizer should always get all touch events, so it should not be
// required to fail by any other gesture recognizer.
- return otherGestureRecognizer != _forwardingRecognizer.get() && otherGestureRecognizer != self;
+ return otherGestureRecognizer != _forwardingRecognizer && otherGestureRecognizer != self;
}
- (BOOL)gestureRecognizer:(UIGestureRecognizer*)gestureRecognizer
@@ -1158,7 +1148,7 @@
// At the start of each gesture sequence, we reset the `_flutterViewController`,
// so that all the touch events in the same sequence are forwarded to the same
// `_flutterViewController`.
- _flutterViewController.reset([_platformViewsController->getFlutterViewController() retain]);
+ _flutterViewController.reset(_platformViewsController->getFlutterViewController());
}
[_flutterViewController.get() touchesBegan:touches withEvent:event];
_currentTouchPointersCount += touches.count;
diff --git a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h
index c2357c3..6373e1f 100644
--- a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h
+++ b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h
@@ -81,18 +81,18 @@
// Determines the rect of the blur effect in the coordinate system of `backdropFilterView`'s
// parentView.
-@property(assign, nonatomic, readonly) CGRect frame;
+@property(nonatomic, readonly) CGRect frame;
// Determines the blur intensity.
//
// It is set as the value of `inputRadius` of the `gaussianFilter` that is internally used.
-@property(assign, nonatomic, readonly) CGFloat blurRadius;
+@property(nonatomic, readonly) CGFloat blurRadius;
// This is the view to use to blur the PlatformView.
//
// It is a modified version of UIKit's `UIVisualEffectView`.
// The inputRadius can be customized and it doesn't add any color saturation to the blurred view.
-@property(nonatomic, retain, readonly) UIVisualEffectView* backdropFilterView;
+@property(nonatomic, readonly) UIVisualEffectView* backdropFilterView;
// For testing only.
+ (void)resetPreparation;
@@ -210,16 +210,19 @@
fml::WeakPtr<flutter::FlutterPlatformViewsController> GetWeakPtr();
- void SetFlutterView(UIView* flutter_view);
+ void SetFlutterView(UIView* flutter_view) __attribute__((cf_audited_transfer));
- void SetFlutterViewController(UIViewController<FlutterViewResponder>* flutter_view_controller);
+ void SetFlutterViewController(UIViewController<FlutterViewResponder>* flutter_view_controller)
+ __attribute__((cf_audited_transfer));
- UIViewController<FlutterViewResponder>* getFlutterViewController();
+ UIViewController<FlutterViewResponder>* getFlutterViewController()
+ __attribute__((cf_audited_transfer));
void RegisterViewFactory(
NSObject<FlutterPlatformViewFactory>* factory,
NSString* factoryId,
- FlutterPlatformViewGestureRecognizersBlockingPolicy gestureRecognizerBlockingPolicy);
+ FlutterPlatformViewGestureRecognizersBlockingPolicy gestureRecognizerBlockingPolicy)
+ __attribute__((cf_audited_transfer));
// Called at the beginning of each frame.
void BeginFrame(SkISize frame_size);
@@ -266,7 +269,8 @@
const std::shared_ptr<IOSContext>& ios_context,
std::unique_ptr<SurfaceFrame> frame);
- void OnMethodCall(FlutterMethodCall* call, FlutterResult result);
+ void OnMethodCall(FlutterMethodCall* call, FlutterResult result)
+ __attribute__((cf_audited_transfer));
// Returns the platform view id if the platform view (or any of its descendant view) is the first
// responder. Returns -1 if no such platform view is found.
@@ -284,10 +288,13 @@
using LayersMap = std::map<int64_t, std::vector<std::shared_ptr<FlutterPlatformViewLayer>>>;
- void OnCreate(FlutterMethodCall* call, FlutterResult result);
- void OnDispose(FlutterMethodCall* call, FlutterResult result);
- void OnAcceptGesture(FlutterMethodCall* call, FlutterResult result);
- void OnRejectGesture(FlutterMethodCall* call, FlutterResult result);
+ void OnCreate(FlutterMethodCall* call, FlutterResult result) __attribute__((cf_audited_transfer));
+ void OnDispose(FlutterMethodCall* call, FlutterResult result)
+ __attribute__((cf_audited_transfer));
+ void OnAcceptGesture(FlutterMethodCall* call, FlutterResult result)
+ __attribute__((cf_audited_transfer));
+ void OnRejectGesture(FlutterMethodCall* call, FlutterResult result)
+ __attribute__((cf_audited_transfer));
// Dispose the views in `views_to_dispose_`.
void DisposeViews();
@@ -301,7 +308,7 @@
// Traverse the `mutators_stack` and return the number of clip operations.
int CountClips(const MutatorsStack& mutators_stack);
- void ClipViewSetMaskView(UIView* clipView);
+ void ClipViewSetMaskView(UIView* clipView) __attribute__((cf_audited_transfer));
// Applies the mutators in the mutators_stack to the UIView chain that was constructed by
// `ReconstructClipViewsChain`
@@ -314,7 +321,7 @@
// rect of the PlatformView, the clip mutator is not applied for performance optimization.
void ApplyMutators(const MutatorsStack& mutators_stack,
UIView* embedded_view,
- const SkRect& bounding_rect);
+ const SkRect& bounding_rect) __attribute__((cf_audited_transfer));
void CompositeWithParams(int64_t view_id, const EmbeddedViewParams& params);
diff --git a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.mm b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.mm
index ebdb0cc..859544e 100644
--- a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.mm
+++ b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.mm
@@ -8,6 +8,8 @@
#include "flutter/fml/platform/darwin/cf_utils.h"
#import "flutter/shell/platform/darwin/ios/ios_surface.h"
+FLUTTER_ASSERT_ARC
+
static constexpr int kMaxPointsInVerb = 4;
static constexpr NSUInteger kFlutterClippingMaskViewPoolCapacity = 5;
@@ -75,7 +77,7 @@
// `YES` if the backdropFilterView has been configured at least once.
@property(nonatomic) BOOL backdropFilterViewConfigured;
-@property(nonatomic, retain) UIVisualEffectView* backdropFilterView;
+@property(nonatomic) UIVisualEffectView* backdropFilterView;
// Updates the `visualEffectView` with the current filter parameters.
// Also sets `self.backdropFilterView` to the updated visualEffectView.
@@ -102,10 +104,9 @@
if (![PlatformViewFilter isUIVisualEffectViewImplementationValid]) {
FML_DLOG(ERROR) << "Apple's API for UIVisualEffectView changed. Update the implementation to "
"access the gaussianBlur CAFilter.";
- [self release];
return nil;
}
- _backdropFilterView = [visualEffectView retain];
+ _backdropFilterView = visualEffectView;
_backdropFilterViewConfigured = NO;
}
return self;
@@ -113,7 +114,6 @@
+ (void)resetPreparation {
_preparedOnce = NO;
- [_gaussianBlurFilter release];
_gaussianBlurFilter = nil;
_indexOfBackdropView = -1;
_indexOfVisualEffectSubview = -1;
@@ -130,7 +130,7 @@
for (NSObject* filter in view.layer.filters) {
if ([[filter valueForKey:@"name"] isEqual:@"gaussianBlur"] &&
[[filter valueForKey:@"inputRadius"] isKindOfClass:[NSNumber class]]) {
- _gaussianBlurFilter = [filter retain];
+ _gaussianBlurFilter = filter;
break;
}
}
@@ -145,13 +145,6 @@
return _indexOfBackdropView > -1 && _indexOfVisualEffectSubview > -1 && _gaussianBlurFilter;
}
-- (void)dealloc {
- [_backdropFilterView release];
- _backdropFilterView = nil;
-
- [super dealloc];
-}
-
- (UIVisualEffectView*)backdropFilterView {
FML_DCHECK(_backdropFilterView);
if (!self.backdropFilterViewConfigured) {
@@ -162,7 +155,7 @@
}
- (void)updateVisualEffectView:(UIVisualEffectView*)visualEffectView {
- NSObject* gaussianBlurFilter = [[_gaussianBlurFilter copy] autorelease];
+ NSObject* gaussianBlurFilter = [_gaussianBlurFilter copy];
FML_DCHECK(gaussianBlurFilter);
UIView* backdropView = visualEffectView.subviews[_indexOfBackdropView];
[gaussianBlurFilter setValue:@(_blurRadius) forKey:@"inputRadius"];
@@ -179,8 +172,8 @@
@interface ChildClippingView ()
-@property(retain, nonatomic) NSArray<PlatformViewFilter*>* filters;
-@property(retain, nonatomic) NSMutableArray<UIVisualEffectView*>* backdropFilterSubviews;
+@property(nonatomic, copy) NSArray<PlatformViewFilter*>* filters;
+@property(nonatomic) NSMutableArray<UIVisualEffectView*>* backdropFilterSubviews;
@end
@@ -222,16 +215,6 @@
}
}
-- (void)dealloc {
- [_filters release];
- _filters = nil;
-
- [_backdropFilterSubviews release];
- _backdropFilterSubviews = nil;
-
- [super dealloc];
-}
-
- (NSMutableArray*)backdropFilterSubviews {
if (!_backdropFilterSubviews) {
_backdropFilterSubviews = [[NSMutableArray alloc] init];
@@ -459,11 +442,11 @@
// The maximum number of `FlutterClippingMaskView` the pool can contain.
// This prevents the pool to grow infinately and limits the maximum memory a pool can use.
-@property(assign, nonatomic) NSUInteger capacity;
+@property(nonatomic) NSUInteger capacity;
// The pool contains the views that are available to use.
// The number of items in the pool must not excceds `capacity`.
-@property(retain, nonatomic) NSMutableSet<FlutterClippingMaskView*>* pool;
+@property(nonatomic) NSMutableSet<FlutterClippingMaskView*>* pool;
@end
@@ -483,11 +466,10 @@
FML_DCHECK(self.pool.count <= self.capacity);
if (self.pool.count == 0) {
// The pool is empty, alloc a new one.
- return
- [[[FlutterClippingMaskView alloc] initWithFrame:frame
- screenScale:[UIScreen mainScreen].scale] autorelease];
+ return [[FlutterClippingMaskView alloc] initWithFrame:frame
+ screenScale:UIScreen.mainScreen.scale];
}
- FlutterClippingMaskView* maskView = [[[self.pool anyObject] retain] autorelease];
+ FlutterClippingMaskView* maskView = [self.pool anyObject];
maskView.frame = frame;
[maskView reset];
[self.pool removeObject:maskView];
@@ -503,10 +485,4 @@
[self.pool addObject:maskView];
}
-- (void)dealloc {
- [_pool release];
-
- [super dealloc];
-}
-
@end
diff --git a/shell/platform/darwin/ios/framework/Source/FlutterView.mm b/shell/platform/darwin/ios/framework/Source/FlutterView.mm
index 1576e0c..e50f903 100644
--- a/shell/platform/darwin/ios/framework/Source/FlutterView.mm
+++ b/shell/platform/darwin/ios/framework/Source/FlutterView.mm
@@ -6,8 +6,13 @@
#include "flutter/fml/platform/darwin/cf_utils.h"
+FLUTTER_ASSERT_ARC
+
+@interface FlutterView ()
+@property(nonatomic, weak) id<FlutterViewEngineDelegate> delegate;
+@end
+
@implementation FlutterView {
- id<FlutterViewEngineDelegate> _delegate;
BOOL _isWideGamutEnabled;
}
@@ -45,7 +50,7 @@
return MTLPixelFormatBGRA8Unorm;
}
- (BOOL)isWideGamutSupported {
- if (![_delegate isUsingImpeller]) {
+ if (!self.delegate.isUsingImpeller) {
return NO;
}
@@ -62,7 +67,6 @@
enableWideGamut:(BOOL)isWideGamutEnabled {
if (delegate == nil) {
NSLog(@"FlutterView delegate was nil.");
- [self release];
return nil;
}
@@ -224,7 +228,7 @@
// TODO(chunhtai): Remove this workaround once iOS provides an
// API to query whether voice control is enabled.
// https://github.com/flutter/flutter/issues/76808.
- [_delegate flutterViewAccessibilityDidCall];
+ [self.delegate flutterViewAccessibilityDidCall];
return NO;
}
diff --git a/shell/platform/darwin/ios/framework/Source/FlutterViewControllerTest.mm b/shell/platform/darwin/ios/framework/Source/FlutterViewControllerTest.mm
index 99bb2ef..b87260c 100644
--- a/shell/platform/darwin/ios/framework/Source/FlutterViewControllerTest.mm
+++ b/shell/platform/darwin/ios/framework/Source/FlutterViewControllerTest.mm
@@ -15,6 +15,7 @@
#import "flutter/shell/platform/darwin/ios/framework/Source/FlutterEmbedderKeyResponder.h"
#import "flutter/shell/platform/darwin/ios/framework/Source/FlutterFakeKeyEvents.h"
#import "flutter/shell/platform/darwin/ios/framework/Source/FlutterTextInputPlugin.h"
+#import "flutter/shell/platform/darwin/ios/framework/Source/FlutterView.h"
#import "flutter/shell/platform/darwin/ios/framework/Source/FlutterViewController_Internal.h"
#import "flutter/shell/platform/darwin/ios/framework/Source/UIViewController+FlutterScreenAndSceneIfLoaded.h"
#import "flutter/shell/platform/darwin/ios/framework/Source/vsync_waiter_ios.h"
@@ -1135,12 +1136,21 @@
- (void)testViewControllerIsReleased {
__weak FlutterViewController* weakViewController;
+ __weak UIView* weakView;
@autoreleasepool {
- FlutterViewController* viewController = [[FlutterViewController alloc] init];
+ FlutterEngine* engine = [[FlutterEngine alloc] init];
+
+ [engine runWithEntrypoint:nil];
+ FlutterViewController* viewController = [[FlutterViewController alloc] initWithEngine:engine
+ nibName:nil
+ bundle:nil];
weakViewController = viewController;
[viewController viewDidLoad];
+ weakView = viewController.view;
+ XCTAssertTrue([viewController.view isKindOfClass:[FlutterView class]]);
}
XCTAssertNil(weakViewController);
+ XCTAssertNil(weakView);
}
#pragma mark - Platform Brightness
diff --git a/testing/ios/IosUnitTests/IosUnitTests.xcodeproj/project.pbxproj b/testing/ios/IosUnitTests/IosUnitTests.xcodeproj/project.pbxproj
index 87f291b..66f378b 100644
--- a/testing/ios/IosUnitTests/IosUnitTests.xcodeproj/project.pbxproj
+++ b/testing/ios/IosUnitTests/IosUnitTests.xcodeproj/project.pbxproj
@@ -74,6 +74,7 @@
D2D361A52B234EAC0018964E /* FlutterMetalLayerTest.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = FlutterMetalLayerTest.mm; sourceTree = "<group>"; };
F7521D7226BB671E005F15C5 /* libios_test_flutter.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libios_test_flutter.dylib; path = "../../../../out/$(FLUTTER_ENGINE)/libios_test_flutter.dylib"; sourceTree = "<group>"; };
F7521D7526BB673E005F15C5 /* libocmock_shared.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libocmock_shared.dylib; path = "../../../../out/$(FLUTTER_ENGINE)/libocmock_shared.dylib"; sourceTree = "<group>"; };
+ F76A3A892BE48F2F00A654F1 /* FlutterPlatformViewsTest.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = FlutterPlatformViewsTest.mm; sourceTree = "<group>"; };
F77E081726FA9CE6003E6E4C /* Flutter.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Flutter.framework; path = "../../../../out/$(FLUTTER_ENGINE)/Flutter.framework"; sourceTree = "<group>"; };
F7A3FDE026B9E0A300EADD61 /* FlutterAppDelegateTest.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = FlutterAppDelegateTest.mm; sourceTree = "<group>"; };
/* End PBXFileReference section */
@@ -99,6 +100,7 @@
0AC232E924BA71D300A85907 /* Source */ = {
isa = PBXGroup;
children = (
+ F76A3A892BE48F2F00A654F1 /* FlutterPlatformViewsTest.mm */,
689EC1E2281B30D3008FEB58 /* FlutterSpellCheckPluginTest.mm */,
68B6091227F62F990036AC78 /* VsyncWaiterIosTest.mm */,
3DD7D38C27D2B81000DA365C /* FlutterUndoManagerPluginTest.mm */,