iOS: Clean up @synthesize directives / ivars (flutter/engine#56665)

In modern Objective-C, `@property` directives automatically generate a backing ivar (property name prefixed with an underscore), the getter, and (for readwrite properties) the setter. `@synthesize` directives are generally only required if the backing ivar has a different name from the property.

Also updates the FlutterMetalLayer API to match CAMetalLayer:
* Adds API_AVAILABLE declaration to match that on CAMetalLayer.
* Eliminates wantsExtendedDynamicRangeContent property as it's also part of CALayer's interface and unused in our implementation.

Also eliminates unnecessary ivars where they're being synthesized by `@property` declarations.

Previously, we were overriding the behaviour of
UIViewController.prefersStatusBarHidden by synthesizing _flutterPrefersStatusBarHidden as a backing ivar. Since we're explicitly overriding the behaviour of a superclass, it's more idiomatic to synthesize a private property or explicitly declare an ivar then explicitly override the getter instead.

Further, this adds documentation to cases where `@synthesize` directives are required, such as:
* Creating a backing ivar for a readonly property.
* Creating a backing ivar for a property with a custom getter/setter.
* Synthesising the ivar, getter, and setter for a property declared in a protocol being implemented.

[C++, Objective-C, Java style guides]: https://github.com/flutter/engine/blob/main/CONTRIBUTING.md#style
This commit is contained in:
Chris Bracken 2024-11-17 16:29:24 -08:00 committed by GitHub
parent 7be64cf1be
commit ab0a04d3a7
12 changed files with 36 additions and 32 deletions

View File

@ -9,16 +9,20 @@
/// Drop-in replacement (as far as Flutter is concerned) for CAMetalLayer /// Drop-in replacement (as far as Flutter is concerned) for CAMetalLayer
/// that can present with transaction from a background thread. /// that can present with transaction from a background thread.
///
/// Properties and method declarations must exactly match those in the
/// CAMetalLayer interface declaration.
@interface FlutterMetalLayer : CALayer @interface FlutterMetalLayer : CALayer
@property(nullable, retain) id<MTLDevice> device; @property(nullable, retain) id<MTLDevice> device;
@property(nullable, readonly) id<MTLDevice> preferredDevice; @property(nullable, readonly)
id<MTLDevice> preferredDevice API_AVAILABLE(macos(10.15), ios(13.0), tvos(13.0))
API_UNAVAILABLE(watchos);
@property MTLPixelFormat pixelFormat; @property MTLPixelFormat pixelFormat;
@property BOOL framebufferOnly; @property BOOL framebufferOnly;
@property CGSize drawableSize; @property CGSize drawableSize;
@property BOOL presentsWithTransaction; @property BOOL presentsWithTransaction;
@property(nullable) CGColorSpaceRef colorspace; @property(nullable) CGColorSpaceRef colorspace;
@property BOOL wantsExtendedDynamicRangeContent;
- (nullable id<CAMetalDrawable>)nextDrawable; - (nullable id<CAMetalDrawable>)nextDrawable;

View File

@ -57,11 +57,7 @@ extern CFTimeInterval display_link_target;
@end @end
@interface FlutterTexture : NSObject { @interface FlutterTexture : NSObject
id<MTLTexture> _texture;
IOSurface* _surface;
CFTimeInterval _presentedTime;
}
@property(readonly, nonatomic) id<MTLTexture> texture; @property(readonly, nonatomic) id<MTLTexture> texture;
@property(readonly, nonatomic) IOSurface* surface; @property(readonly, nonatomic) IOSurface* surface;
@ -72,11 +68,6 @@ extern CFTimeInterval display_link_target;
@implementation FlutterTexture @implementation FlutterTexture
@synthesize texture = _texture;
@synthesize surface = _surface;
@synthesize presentedTime = _presentedTime;
@synthesize waitingForCompletion;
- (instancetype)initWithTexture:(id<MTLTexture>)texture surface:(IOSurface*)surface { - (instancetype)initWithTexture:(id<MTLTexture>)texture surface:(IOSurface*)surface {
if (self = [super init]) { if (self = [super init]) {
_texture = texture; _texture = texture;
@ -187,13 +178,6 @@ extern CFTimeInterval display_link_target;
@implementation FlutterMetalLayer @implementation FlutterMetalLayer
@synthesize preferredDevice = _preferredDevice;
@synthesize device = _device;
@synthesize pixelFormat = _pixelFormat;
@synthesize framebufferOnly = _framebufferOnly;
@synthesize colorspace = _colorspace;
@synthesize wantsExtendedDynamicRangeContent = _wantsExtendedDynamicRangeContent;
- (instancetype)init { - (instancetype)init {
if (self = [super init]) { if (self = [super init]) {
_preferredDevice = MTLCreateSystemDefaultDevice(); _preferredDevice = MTLCreateSystemDefaultDevice();

View File

@ -662,6 +662,7 @@ static BOOL IsSelectionRectBoundaryCloserToPoint(CGPoint point,
@implementation FlutterTextSelectionRect @implementation FlutterTextSelectionRect
// Synthesize properties declared readonly in UITextSelectionRect.
@synthesize rect = _rect; @synthesize rect = _rect;
@synthesize writingDirection = _writingDirection; @synthesize writingDirection = _writingDirection;
@synthesize containsStart = _containsStart; @synthesize containsStart = _containsStart;

View File

@ -79,6 +79,9 @@ typedef struct MouseState {
@property(nonatomic, assign) BOOL isHomeIndicatorHidden; @property(nonatomic, assign) BOOL isHomeIndicatorHidden;
@property(nonatomic, assign) BOOL isPresentingViewControllerAnimating; @property(nonatomic, assign) BOOL isPresentingViewControllerAnimating;
// Internal state backing override of UIView.prefersStatusBarHidden.
@property(nonatomic, assign) BOOL flutterPrefersStatusBarHidden;
@property(nonatomic, strong) NSMutableSet<NSNumber*>* ongoingTouches; @property(nonatomic, strong) NSMutableSet<NSNumber*>* ongoingTouches;
// This scroll view is a workaround to accommodate iOS 13 and higher. There isn't a way to get // This scroll view is a workaround to accommodate iOS 13 and higher. There isn't a way to get
// touches on the status bar to trigger scrolling to the top of a scroll view. We place a // touches on the status bar to trigger scrolling to the top of a scroll view. We place a
@ -157,9 +160,13 @@ typedef struct MouseState {
MouseState _mouseState; MouseState _mouseState;
} }
// Synthesize properties with an overridden getter/setter.
@synthesize viewOpaque = _viewOpaque; @synthesize viewOpaque = _viewOpaque;
@synthesize displayingFlutterUI = _displayingFlutterUI; @synthesize displayingFlutterUI = _displayingFlutterUI;
@synthesize prefersStatusBarHidden = _flutterPrefersStatusBarHidden;
// TODO(dkwingsmt): https://github.com/flutter/flutter/issues/138168
// No backing ivar is currently required; when multiple views are supported, we'll need to
// synthesize the ivar and store the view identifier.
@dynamic viewIdentifier; @dynamic viewIdentifier;
#pragma mark - Manage and override all designated initializers #pragma mark - Manage and override all designated initializers
@ -2302,14 +2309,14 @@ static flutter::PointerData::DeviceKind DeviceKindFromTouchType(UITouch* touch)
} }
- (void)setPrefersStatusBarHidden:(BOOL)hidden { - (void)setPrefersStatusBarHidden:(BOOL)hidden {
if (hidden != _flutterPrefersStatusBarHidden) { if (hidden != self.flutterPrefersStatusBarHidden) {
_flutterPrefersStatusBarHidden = hidden; self.flutterPrefersStatusBarHidden = hidden;
[self setNeedsStatusBarAppearanceUpdate]; [self setNeedsStatusBarAppearanceUpdate];
} }
} }
- (BOOL)prefersStatusBarHidden { - (BOOL)prefersStatusBarHidden {
return _flutterPrefersStatusBarHidden; return self.flutterPrefersStatusBarHidden;
} }
#pragma mark - Platform views #pragma mark - Platform views

View File

@ -38,21 +38,26 @@ using namespace flutter::testing;
/// Sometimes we have to use a custom mock to avoid retain cycles in OCMock. /// Sometimes we have to use a custom mock to avoid retain cycles in OCMock.
/// Used for testing low memory notification. /// Used for testing low memory notification.
@interface FlutterEnginePartialMock : FlutterEngine @interface FlutterEnginePartialMock : FlutterEngine
@property(nonatomic, strong) FlutterBasicMessageChannel* lifecycleChannel; @property(nonatomic, strong) FlutterBasicMessageChannel* lifecycleChannel;
@property(nonatomic, strong) FlutterBasicMessageChannel* keyEventChannel; @property(nonatomic, strong) FlutterBasicMessageChannel* keyEventChannel;
@property(nonatomic, weak) FlutterViewController* viewController; @property(nonatomic, weak) FlutterViewController* viewController;
@property(nonatomic, strong) FlutterTextInputPlugin* textInputPlugin; @property(nonatomic, strong) FlutterTextInputPlugin* textInputPlugin;
@property(nonatomic, assign) BOOL didCallNotifyLowMemory; @property(nonatomic, assign) BOOL didCallNotifyLowMemory;
- (FlutterTextInputPlugin*)textInputPlugin; - (FlutterTextInputPlugin*)textInputPlugin;
- (void)sendKeyEvent:(const FlutterKeyEvent&)event - (void)sendKeyEvent:(const FlutterKeyEvent&)event
callback:(nullable FlutterKeyEventCallback)callback callback:(nullable FlutterKeyEventCallback)callback
userData:(nullable void*)userData; userData:(nullable void*)userData;
@end @end
@implementation FlutterEnginePartialMock @implementation FlutterEnginePartialMock
@synthesize viewController;
// Synthesize properties declared readonly in FlutterEngine.
@synthesize lifecycleChannel; @synthesize lifecycleChannel;
@synthesize keyEventChannel; @synthesize keyEventChannel;
@synthesize viewController;
@synthesize textInputPlugin; @synthesize textInputPlugin;
- (void)notifyLowMemory { - (void)notifyLowMemory {

View File

@ -22,6 +22,7 @@ static const UIAccessibilityTraits kUIAccessibilityTraitUndocumentedEmptyLine =
@implementation FlutterInactiveTextInput @implementation FlutterInactiveTextInput
// Synthesize properties declared in UITextInput protocol.
@synthesize beginningOfDocument = _beginningOfDocument; @synthesize beginningOfDocument = _beginningOfDocument;
@synthesize endOfDocument = _endOfDocument; @synthesize endOfDocument = _endOfDocument;
@synthesize inputDelegate = _inputDelegate; @synthesize inputDelegate = _inputDelegate;

View File

@ -29,6 +29,7 @@
@implementation FlutterChannelKeyResponder @implementation FlutterChannelKeyResponder
// Synthesize properties declared in FlutterKeyPrimaryResponder protocol.
@synthesize layoutMap; @synthesize layoutMap;
- (nonnull instancetype)initWithChannel:(nonnull FlutterBasicMessageChannel*)channel { - (nonnull instancetype)initWithChannel:(nonnull FlutterBasicMessageChannel*)channel {

View File

@ -473,6 +473,7 @@ struct FlutterKeyPendingResponse {
@implementation FlutterEmbedderKeyResponder @implementation FlutterEmbedderKeyResponder
// Synthesize properties declared in FlutterKeyPrimaryResponder protocol.
@synthesize layoutMap; @synthesize layoutMap;
- (nonnull instancetype)initWithSendEvent:(FlutterSendEmbedderKeyEvent)sendEvent { - (nonnull instancetype)initWithSendEvent:(FlutterSendEmbedderKeyEvent)sendEvent {

View File

@ -25,6 +25,8 @@
@end @end
@implementation FakePluginRegistrar @implementation FakePluginRegistrar
// Synthesize properties declared in FlutterPluginRegistrar protocol.
@synthesize messenger; @synthesize messenger;
@synthesize textures; @synthesize textures;
@synthesize view; @synthesize view;

View File

@ -28,8 +28,6 @@
FlutterThreadSynchronizer* _synchronizer; FlutterThreadSynchronizer* _synchronizer;
} }
@synthesize synchronizer = _synchronizer;
- (nullable instancetype)init { - (nullable instancetype)init {
self = [super init]; self = [super init];
if (self != nil) { if (self != nil) {

View File

@ -7,8 +7,7 @@
#import "flutter/testing/testing.h" #import "flutter/testing/testing.h"
@interface TestDisplayLink : FlutterDisplayLink { @interface TestDisplayLink : FlutterDisplayLink
}
@property(nonatomic) CFTimeInterval nominalOutputRefreshPeriod; @property(nonatomic) CFTimeInterval nominalOutputRefreshPeriod;
@ -16,20 +15,19 @@
@implementation TestDisplayLink @implementation TestDisplayLink
// Synthesize properties declared readonly in FlutterDisplayLink.
@synthesize nominalOutputRefreshPeriod = _nominalOutputRefreshPeriod; @synthesize nominalOutputRefreshPeriod = _nominalOutputRefreshPeriod;
@synthesize delegate = _delegate;
@synthesize paused = _paused;
- (instancetype)init { - (instancetype)init {
if (self = [super init]) { if (self = [super init]) {
_paused = YES; self.paused = YES;
} }
return self; return self;
} }
- (void)tickWithTimestamp:(CFTimeInterval)timestamp - (void)tickWithTimestamp:(CFTimeInterval)timestamp
targetTimestamp:(CFTimeInterval)targetTimestamp { targetTimestamp:(CFTimeInterval)targetTimestamp {
[_delegate onDisplayLink:timestamp targetTimestamp:targetTimestamp]; [self.delegate onDisplayLink:timestamp targetTimestamp:targetTimestamp];
} }
- (void)invalidate { - (void)invalidate {

View File

@ -341,7 +341,9 @@ static void OnKeyboardLayoutChanged(CFNotificationCenterRef center,
FlutterThreadSynchronizer* _threadSynchronizer; FlutterThreadSynchronizer* _threadSynchronizer;
} }
// Synthesize properties declared readonly.
@synthesize viewIdentifier = _viewIdentifier; @synthesize viewIdentifier = _viewIdentifier;
@dynamic accessibilityBridge; @dynamic accessibilityBridge;
/** /**