Skip to content

Commit c9f8ebe

Browse files
authored
iOS: Eliminate unnecessary use of NSClassFromString (flutter/engine#56660)
When performing `isKindOfClass` checks, we were occasionally looking up the class in question using `NSClassFromString()`, instead we now check against the class directly, which has the added benefit of being type-safe, and not succeptible to string typos. Moves the declaration of ForwardingGestureRecognizer and FlutterDelayingGestureRecognizer to the FlutterPlatfomViews_Internal.h header, which is non-public. [C++, Objective-C, Java style guides]: https://github.com/flutter/engine/blob/main/CONTRIBUTING.md#style
1 parent 33b5f9d commit c9f8ebe

File tree

6 files changed

+51
-53
lines changed

6 files changed

+51
-53
lines changed

engine/src/flutter/shell/platform/darwin/ios/framework/Source/FlutterOverlayView.mm

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ - (instancetype)initWithContentsScale:(CGFloat)contentsScale
4242
pixelFormat:(MTLPixelFormat)pixelFormat {
4343
self = [self init];
4444

45-
if ([self.layer isKindOfClass:NSClassFromString(@"CAMetalLayer")]) {
45+
if ([self.layer isKindOfClass:[CAMetalLayer class]]) {
4646
self.layer.allowsGroupOpacity = NO;
4747
self.layer.contentsScale = contentsScale;
4848
self.layer.rasterizationScale = contentsScale;

engine/src/flutter/shell/platform/darwin/ios/framework/Source/FlutterPlatformViewsTest.mm

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2458,7 +2458,7 @@ - (void)testSetFlutterViewControllerAfterCreateCanStillDispatchTouchEvents {
24582458
// Find ForwardGestureRecognizer
24592459
UIGestureRecognizer* forwardGectureRecognizer = nil;
24602460
for (UIGestureRecognizer* gestureRecognizer in touchInteceptorView.gestureRecognizers) {
2461-
if ([gestureRecognizer isKindOfClass:NSClassFromString(@"ForwardingGestureRecognizer")]) {
2461+
if ([gestureRecognizer isKindOfClass:[ForwardingGestureRecognizer class]]) {
24622462
forwardGectureRecognizer = gestureRecognizer;
24632463
break;
24642464
}
@@ -2525,7 +2525,7 @@ - (void)testSetFlutterViewControllerInTheMiddleOfTouchEventShouldStillAllowGestu
25252525
// Find ForwardGestureRecognizer
25262526
UIGestureRecognizer* forwardGectureRecognizer = nil;
25272527
for (UIGestureRecognizer* gestureRecognizer in touchInteceptorView.gestureRecognizers) {
2528-
if ([gestureRecognizer isKindOfClass:NSClassFromString(@"ForwardingGestureRecognizer")]) {
2528+
if ([gestureRecognizer isKindOfClass:[ForwardingGestureRecognizer class]]) {
25292529
forwardGectureRecognizer = gestureRecognizer;
25302530
break;
25312531
}
@@ -2649,7 +2649,7 @@ - (void)testSetFlutterViewControllerInTheMiddleOfTouchEventShouldStillAllowGestu
26492649
// Find ForwardGestureRecognizer
26502650
UIGestureRecognizer* forwardGectureRecognizer = nil;
26512651
for (UIGestureRecognizer* gestureRecognizer in touchInteceptorView.gestureRecognizers) {
2652-
if ([gestureRecognizer isKindOfClass:NSClassFromString(@"ForwardingGestureRecognizer")]) {
2652+
if ([gestureRecognizer isKindOfClass:[ForwardingGestureRecognizer class]]) {
26532653
forwardGectureRecognizer = gestureRecognizer;
26542654
break;
26552655
}
@@ -2763,7 +2763,7 @@ - (void)testFlutterPlatformViewTouchesCancelledEventAreForcedToBeCancelled {
27632763
// Find ForwardGestureRecognizer
27642764
UIGestureRecognizer* forwardGectureRecognizer = nil;
27652765
for (UIGestureRecognizer* gestureRecognizer in touchInteceptorView.gestureRecognizers) {
2766-
if ([gestureRecognizer isKindOfClass:NSClassFromString(@"ForwardingGestureRecognizer")]) {
2766+
if ([gestureRecognizer isKindOfClass:[ForwardingGestureRecognizer class]]) {
27672767
forwardGectureRecognizer = gestureRecognizer;
27682768
break;
27692769
}
@@ -2828,7 +2828,7 @@ - (void)testFlutterPlatformViewTouchesEndedOrTouchesCancelledEventDoesNotFailThe
28282828
// Find ForwardGestureRecognizer
28292829
__block UIGestureRecognizer* forwardGestureRecognizer = nil;
28302830
for (UIGestureRecognizer* gestureRecognizer in touchInteceptorView.gestureRecognizers) {
2831-
if ([gestureRecognizer isKindOfClass:NSClassFromString(@"ForwardingGestureRecognizer")]) {
2831+
if ([gestureRecognizer isKindOfClass:[ForwardingGestureRecognizer class]]) {
28322832
forwardGestureRecognizer = gestureRecognizer;
28332833
break;
28342834
}
@@ -2851,7 +2851,7 @@ - (void)testFlutterPlatformViewTouchesEndedOrTouchesCancelledEventDoesNotFailThe
28512851
dispatch_async(dispatch_get_main_queue(), ^{
28522852
// Re-query forward gesture recognizer since it's recreated.
28532853
for (UIGestureRecognizer* gestureRecognizer in touchInteceptorView.gestureRecognizers) {
2854-
if ([gestureRecognizer isKindOfClass:NSClassFromString(@"ForwardingGestureRecognizer")]) {
2854+
if ([gestureRecognizer isKindOfClass:[ForwardingGestureRecognizer class]]) {
28552855
forwardGestureRecognizer = gestureRecognizer;
28562856
break;
28572857
}
@@ -2873,7 +2873,7 @@ - (void)testFlutterPlatformViewTouchesEndedOrTouchesCancelledEventDoesNotFailThe
28732873
dispatch_async(dispatch_get_main_queue(), ^{
28742874
// Re-query forward gesture recognizer since it's recreated.
28752875
for (UIGestureRecognizer* gestureRecognizer in touchInteceptorView.gestureRecognizers) {
2876-
if ([gestureRecognizer isKindOfClass:NSClassFromString(@"ForwardingGestureRecognizer")]) {
2876+
if ([gestureRecognizer isKindOfClass:[ForwardingGestureRecognizer class]]) {
28772877
forwardGestureRecognizer = gestureRecognizer;
28782878
break;
28792879
}

engine/src/flutter/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h

Lines changed: 40 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,6 @@
2121
#import "flutter/shell/platform/darwin/ios/framework/Source/platform_views_controller.h"
2222
#import "flutter/shell/platform/darwin/ios/ios_context.h"
2323

24-
@class FlutterTouchInterceptingView;
25-
2624
// A UIView that acts as a clipping mask for the |ChildClippingView|.
2725
//
2826
// On the [UIView drawRect:] method, this view performs a series of clipping operations and sets the
@@ -159,4 +157,44 @@
159157
@property(nonatomic, readonly) BOOL flt_hasFirstResponderInViewHierarchySubtree;
160158
@end
161159

160+
// This recognizer delays touch events from being dispatched to the responder chain until it failed
161+
// recognizing a gesture.
162+
//
163+
// We only fail this recognizer when asked to do so by the Flutter framework (which does so by
164+
// invoking an acceptGesture method on the platform_views channel). And this is how we allow the
165+
// Flutter framework to delay or prevent the embedded view from getting a touch sequence.
166+
@interface FlutterDelayingGestureRecognizer : UIGestureRecognizer <UIGestureRecognizerDelegate>
167+
168+
// Indicates that if the `FlutterDelayingGestureRecognizer`'s state should be set to
169+
// `UIGestureRecognizerStateEnded` during next `touchesEnded` call.
170+
@property(nonatomic) BOOL shouldEndInNextTouchesEnded;
171+
172+
// Indicates that the `FlutterDelayingGestureRecognizer`'s `touchesEnded` has been invoked without
173+
// setting the state to `UIGestureRecognizerStateEnded`.
174+
@property(nonatomic) BOOL touchedEndedWithoutBlocking;
175+
176+
@property(nonatomic) UIGestureRecognizer* forwardingRecognizer;
177+
178+
- (instancetype)initWithTarget:(id)target
179+
action:(SEL)action
180+
forwardingRecognizer:(UIGestureRecognizer*)forwardingRecognizer;
181+
@end
182+
183+
// While the FlutterDelayingGestureRecognizer is preventing touches from hitting the responder chain
184+
// the touch events are not arriving to the FlutterView (and thus not arriving to the Flutter
185+
// framework). We use this gesture recognizer to dispatch the events directly to the FlutterView
186+
// while during this phase.
187+
//
188+
// If the Flutter framework decides to dispatch events to the embedded view, we fail the
189+
// FlutterDelayingGestureRecognizer which sends the events up the responder chain. But since the
190+
// events are handled by the embedded view they are not delivered to the Flutter framework in this
191+
// phase as well. So during this phase as well the ForwardingGestureRecognizer dispatched the events
192+
// directly to the FlutterView.
193+
@interface ForwardingGestureRecognizer : UIGestureRecognizer <UIGestureRecognizerDelegate>
194+
- (instancetype)initWithTarget:(id)target
195+
platformViewsController:
196+
(fml::WeakPtr<flutter::PlatformViewsController>)platformViewsController;
197+
- (ForwardingGestureRecognizer*)recreateRecognizerWithTarget:(id)target;
198+
@end
199+
162200
#endif // FLUTTER_SHELL_PLATFORM_DARWIN_IOS_FRAMEWORK_SOURCE_FLUTTERPLATFORMVIEWS_INTERNAL_H_

engine/src/flutter/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.mm

Lines changed: 0 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -510,46 +510,6 @@ - (BOOL)flt_hasFirstResponderInViewHierarchySubtree {
510510
}
511511
@end
512512

513-
// This recognizer delays touch events from being dispatched to the responder chain until it failed
514-
// recognizing a gesture.
515-
//
516-
// We only fail this recognizer when asked to do so by the Flutter framework (which does so by
517-
// invoking an acceptGesture method on the platform_views channel). And this is how we allow the
518-
// Flutter framework to delay or prevent the embedded view from getting a touch sequence.
519-
@interface FlutterDelayingGestureRecognizer : UIGestureRecognizer <UIGestureRecognizerDelegate>
520-
521-
// Indicates that if the `FlutterDelayingGestureRecognizer`'s state should be set to
522-
// `UIGestureRecognizerStateEnded` during next `touchesEnded` call.
523-
@property(nonatomic) BOOL shouldEndInNextTouchesEnded;
524-
525-
// Indicates that the `FlutterDelayingGestureRecognizer`'s `touchesEnded` has been invoked without
526-
// setting the state to `UIGestureRecognizerStateEnded`.
527-
@property(nonatomic) BOOL touchedEndedWithoutBlocking;
528-
529-
@property(nonatomic) UIGestureRecognizer* forwardingRecognizer;
530-
531-
- (instancetype)initWithTarget:(id)target
532-
action:(SEL)action
533-
forwardingRecognizer:(UIGestureRecognizer*)forwardingRecognizer;
534-
@end
535-
536-
// While the FlutterDelayingGestureRecognizer is preventing touches from hitting the responder chain
537-
// the touch events are not arriving to the FlutterView (and thus not arriving to the Flutter
538-
// framework). We use this gesture recognizer to dispatch the events directly to the FlutterView
539-
// while during this phase.
540-
//
541-
// If the Flutter framework decides to dispatch events to the embedded view, we fail the
542-
// FlutterDelayingGestureRecognizer which sends the events up the responder chain. But since the
543-
// events are handled by the embedded view they are not delivered to the Flutter framework in this
544-
// phase as well. So during this phase as well the ForwardingGestureRecognizer dispatched the events
545-
// directly to the FlutterView.
546-
@interface ForwardingGestureRecognizer : UIGestureRecognizer <UIGestureRecognizerDelegate>
547-
- (instancetype)initWithTarget:(id)target
548-
platformViewsController:
549-
(fml::WeakPtr<flutter::PlatformViewsController>)platformViewsController;
550-
- (ForwardingGestureRecognizer*)recreateRecognizerWithTarget:(id)target;
551-
@end
552-
553513
@interface FlutterTouchInterceptingView ()
554514
@property(nonatomic, weak, readonly) UIView* embeddedView;
555515
@property(nonatomic, readonly) FlutterDelayingGestureRecognizer* delayingRecognizer;

engine/src/flutter/shell/platform/darwin/ios/framework/Source/FlutterView.mm

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ - (UIScreen*)screen {
4040
}
4141

4242
- (MTLPixelFormat)pixelFormat {
43-
if ([self.layer isKindOfClass:NSClassFromString(@"CAMetalLayer")]) {
43+
if ([self.layer isKindOfClass:[CAMetalLayer class]]) {
4444
// It is a known Apple bug that CAMetalLayer incorrectly reports its supported
4545
// SDKs. It is, in fact, available since iOS 8.
4646
#pragma clang diagnostic push
@@ -93,7 +93,7 @@ static void PrintWideGamutWarningOnce() {
9393
}
9494

9595
- (void)layoutSubviews {
96-
if ([self.layer isKindOfClass:NSClassFromString(@"CAMetalLayer")]) {
96+
if ([self.layer isKindOfClass:[CAMetalLayer class]]) {
9797
// It is a known Apple bug that CAMetalLayer incorrectly reports its supported
9898
// SDKs. It is, in fact, available since iOS 8.
9999
#pragma clang diagnostic push

engine/src/flutter/shell/platform/darwin/ios/framework/Source/FlutterViewTest.mm

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ - (void)testIgnoreWideColorWithoutImpeller {
6262
delegate.isUsingImpeller = NO;
6363
FlutterView* view = [[FlutterView alloc] initWithDelegate:delegate opaque:NO enableWideGamut:YES];
6464
[view layoutSubviews];
65-
XCTAssertTrue([view.layer isKindOfClass:NSClassFromString(@"CAMetalLayer")]);
65+
XCTAssertTrue([view.layer isKindOfClass:[CAMetalLayer class]]);
6666
CAMetalLayer* layer = (CAMetalLayer*)view.layer;
6767
XCTAssertEqual(layer.pixelFormat, MTLPixelFormatBGRA8Unorm);
6868
}

0 commit comments

Comments
 (0)