iOS: Apply nullability annotations to FlutterPlatformViewsController (flutter/engine#56839)

Applies non-null by default annotations to
FlutterPlatformViewsController with opt-outs where necessary. Updates unit tests to create graphics contexts where requried.

[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-28 09:44:23 -08:00 committed by GitHub
parent 8b237d39d5
commit f988f524fe
3 changed files with 48 additions and 42 deletions

View File

@ -23,24 +23,23 @@
#import "flutter/shell/platform/darwin/ios/framework/Source/overlay_layer_pool.h" #import "flutter/shell/platform/darwin/ios/framework/Source/overlay_layer_pool.h"
#import "flutter/shell/platform/darwin/ios/ios_context.h" #import "flutter/shell/platform/darwin/ios/ios_context.h"
NS_ASSUME_NONNULL_BEGIN
@class FlutterTouchInterceptingView; @class FlutterTouchInterceptingView;
@class FlutterClippingMaskViewPool; @class FlutterClippingMaskViewPool;
@interface FlutterPlatformViewsController : NSObject @interface FlutterPlatformViewsController : NSObject
- (id)init NS_DESIGNATED_INITIALIZER; - (instancetype)init NS_DESIGNATED_INITIALIZER;
/// The task runner used to post rendering tasks to the platform thread. /// The task runner used to post rendering tasks to the platform thread.
@property(nonatomic, assign) const fml::RefPtr<fml::TaskRunner>& taskRunner; @property(nonatomic, assign) const fml::RefPtr<fml::TaskRunner>& taskRunner;
/// The flutter view. /// The flutter view.
@property(nonatomic, weak) UIView* flutterView; @property(nonatomic, weak) UIView* _Nullable flutterView;
/// @brief The flutter view controller. /// @brief The flutter view controller.
@property(nonatomic, weak) UIViewController<FlutterViewResponder>* flutterViewController; @property(nonatomic, weak) UIViewController<FlutterViewResponder>* _Nullable flutterViewController;
/// @brief Retrieve the view controller.
- (UIViewController<FlutterViewResponder>*)flutterViewController;
/// @brief set the factory used to construct embedded UI Views. /// @brief set the factory used to construct embedded UI Views.
- (void)registerViewFactory:(NSObject<FlutterPlatformViewFactory>*)factory - (void)registerViewFactory:(NSObject<FlutterPlatformViewFactory>*)factory
@ -101,7 +100,7 @@
/// Called from the raster thread. /// Called from the raster thread.
- (BOOL)submitFrame:(std::unique_ptr<flutter::SurfaceFrame>)frame - (BOOL)submitFrame:(std::unique_ptr<flutter::SurfaceFrame>)frame
withIosContext:(const std::shared_ptr<flutter::IOSContext>&)iosContext withIosContext:(const std::shared_ptr<flutter::IOSContext>&)iosContext
grContext:(GrDirectContext*)grContext; grContext:(GrDirectContext* _Nullable)grContext;
/// @brief Handler for platform view message channels. /// @brief Handler for platform view message channels.
- (void)onMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result; - (void)onMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result;
@ -130,7 +129,7 @@
// If the `PlatformViewsController` does not contain any `FlutterPlatformView` object or // If the `PlatformViewsController` does not contain any `FlutterPlatformView` object or
// a `FlutterPlatformView` object associated with the view_id cannot be found, the method // a `FlutterPlatformView` object associated with the view_id cannot be found, the method
// returns nil. // returns nil.
- (UIView*)platformViewForId:(int64_t)viewId; - (UIView* _Nullable)platformViewForId:(int64_t)viewId;
// Composite the PlatformView with `viewId`. // Composite the PlatformView with `viewId`.
// //
@ -146,4 +145,6 @@
@end @end
NS_ASSUME_NONNULL_END
#endif // FLUTTER_SHELL_PLATFORM_DARWIN_IOS_FRAMEWORK_SOURCE_FLUTTERPLATFORMVIEWSCONTROLLER_H_ #endif // FLUTTER_SHELL_PLATFORM_DARWIN_IOS_FRAMEWORK_SOURCE_FLUTTERPLATFORMVIEWSCONTROLLER_H_

View File

@ -705,6 +705,7 @@ static bool ClipRRectContainsPlatformViewBoundingRect(const SkRRect& clip_rrect,
} }
- (flutter::DlCanvas*)compositeEmbeddedViewWithId:(int64_t)viewId { - (flutter::DlCanvas*)compositeEmbeddedViewWithId:(int64_t)viewId {
FML_DCHECK(self.slices.find(viewId) != self.slices.end());
return self.slices[viewId]->canvas(); return self.slices[viewId]->canvas();
} }

View File

@ -8,6 +8,8 @@
#import <UIKit/UIKit.h> #import <UIKit/UIKit.h>
#import <XCTest/XCTest.h> #import <XCTest/XCTest.h>
#include <memory>
#include "flutter/display_list/effects/dl_image_filters.h" #include "flutter/display_list/effects/dl_image_filters.h"
#include "flutter/fml/synchronization/count_down_latch.h" #include "flutter/fml/synchronization/count_down_latch.h"
#include "flutter/fml/thread.h" #include "flutter/fml/thread.h"
@ -17,6 +19,7 @@
#import "flutter/shell/platform/darwin/ios/framework/Source/FlutterPlatformViewsController.h" #import "flutter/shell/platform/darwin/ios/framework/Source/FlutterPlatformViewsController.h"
#import "flutter/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h" #import "flutter/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h"
#import "flutter/shell/platform/darwin/ios/framework/Source/FlutterTouchInterceptingView_Test.h" #import "flutter/shell/platform/darwin/ios/framework/Source/FlutterTouchInterceptingView_Test.h"
#include "flutter/shell/platform/darwin/ios/ios_context_noop.h"
#include "flutter/shell/platform/darwin/ios/platform_view_ios.h" #include "flutter/shell/platform/darwin/ios/platform_view_ios.h"
FLUTTER_ASSERT_ARC FLUTTER_ASSERT_ARC
@ -3103,8 +3106,9 @@ fml::RefPtr<fml::TaskRunner> GetDefaultTaskRunner() {
[](const flutter::SurfaceFrame& surface_frame, flutter::DlCanvas* canvas) { return false; }, [](const flutter::SurfaceFrame& surface_frame, flutter::DlCanvas* canvas) { return false; },
[](const flutter::SurfaceFrame& surface_frame) { return true; }, [](const flutter::SurfaceFrame& surface_frame) { return true; },
/*frame_size=*/SkISize::Make(800, 600)); /*frame_size=*/SkISize::Make(800, 600));
XCTAssertFalse([flutterPlatformViewsController submitFrame:std::move(mock_surface) XCTAssertFalse([flutterPlatformViewsController
withIosContext:nil submitFrame:std::move(mock_surface)
withIosContext:std::make_shared<flutter::IOSContextNoop>()
grContext:nil]); grContext:nil]);
auto embeddedViewParams_2 = auto embeddedViewParams_2 =
@ -3120,8 +3124,9 @@ fml::RefPtr<fml::TaskRunner> GetDefaultTaskRunner() {
[](const flutter::SurfaceFrame& surface_frame, flutter::DlCanvas* canvas) { return true; }, [](const flutter::SurfaceFrame& surface_frame, flutter::DlCanvas* canvas) { return true; },
[](const flutter::SurfaceFrame& surface_frame) { return true; }, [](const flutter::SurfaceFrame& surface_frame) { return true; },
/*frame_size=*/SkISize::Make(800, 600)); /*frame_size=*/SkISize::Make(800, 600));
XCTAssertTrue([flutterPlatformViewsController submitFrame:std::move(mock_surface_submit_true) XCTAssertTrue([flutterPlatformViewsController
withIosContext:nil submitFrame:std::move(mock_surface_submit_true)
withIosContext:std::make_shared<flutter::IOSContextNoop>()
grContext:nil]); grContext:nil]);
} }
@ -3328,9 +3333,9 @@ fml::RefPtr<fml::TaskRunner> GetDefaultTaskRunner() {
[](const flutter::SurfaceFrame& surface_frame, flutter::DlCanvas* canvas) { return true; }, [](const flutter::SurfaceFrame& surface_frame, flutter::DlCanvas* canvas) { return true; },
[](const flutter::SurfaceFrame& surface_frame) { return true; }, [](const flutter::SurfaceFrame& surface_frame) { return true; },
/*frame_size=*/SkISize::Make(800, 600)); /*frame_size=*/SkISize::Make(800, 600));
XCTAssertTrue([flutterPlatformViewsController
XCTAssertTrue([flutterPlatformViewsController submitFrame:std::move(mock_surface) submitFrame:std::move(mock_surface)
withIosContext:nil withIosContext:std::make_shared<flutter::IOSContextNoop>()
grContext:nil]); grContext:nil]);
// platform view is wrapped by touch interceptor, which itself is wrapped by clipping view. // platform view is wrapped by touch interceptor, which itself is wrapped by clipping view.
@ -3359,8 +3364,9 @@ fml::RefPtr<fml::TaskRunner> GetDefaultTaskRunner() {
[](const flutter::SurfaceFrame& surface_frame, flutter::DlCanvas* canvas) { return true; }, [](const flutter::SurfaceFrame& surface_frame, flutter::DlCanvas* canvas) { return true; },
[](const flutter::SurfaceFrame& surface_frame) { return true; }, [](const flutter::SurfaceFrame& surface_frame) { return true; },
/*frame_size=*/SkISize::Make(800, 600)); /*frame_size=*/SkISize::Make(800, 600));
XCTAssertTrue([flutterPlatformViewsController submitFrame:std::move(mock_surface) XCTAssertTrue([flutterPlatformViewsController
withIosContext:nil submitFrame:std::move(mock_surface)
withIosContext:std::make_shared<flutter::IOSContextNoop>()
grContext:nil]); grContext:nil]);
XCTAssertTrue([flutterView.subviews indexOfObject:clippingView1] > XCTAssertTrue([flutterView.subviews indexOfObject:clippingView1] >
@ -3442,9 +3448,9 @@ fml::RefPtr<fml::TaskRunner> GetDefaultTaskRunner() {
[](const flutter::SurfaceFrame& surface_frame, flutter::DlCanvas* canvas) { return true; }, [](const flutter::SurfaceFrame& surface_frame, flutter::DlCanvas* canvas) { return true; },
[](const flutter::SurfaceFrame& surface_frame) { return true; }, [](const flutter::SurfaceFrame& surface_frame) { return true; },
/*frame_size=*/SkISize::Make(800, 600)); /*frame_size=*/SkISize::Make(800, 600));
XCTAssertTrue([flutterPlatformViewsController
XCTAssertTrue([flutterPlatformViewsController submitFrame:std::move(mock_surface) submitFrame:std::move(mock_surface)
withIosContext:nil withIosContext:std::make_shared<flutter::IOSContextNoop>()
grContext:nil]); grContext:nil]);
// platform view is wrapped by touch interceptor, which itself is wrapped by clipping view. // platform view is wrapped by touch interceptor, which itself is wrapped by clipping view.
@ -3473,9 +3479,9 @@ fml::RefPtr<fml::TaskRunner> GetDefaultTaskRunner() {
[](const flutter::SurfaceFrame& surface_frame, flutter::DlCanvas* canvas) { return true; }, [](const flutter::SurfaceFrame& surface_frame, flutter::DlCanvas* canvas) { return true; },
[](const flutter::SurfaceFrame& surface_frame) { return true; }, [](const flutter::SurfaceFrame& surface_frame) { return true; },
/*frame_size=*/SkISize::Make(800, 600)); /*frame_size=*/SkISize::Make(800, 600));
XCTAssertTrue([flutterPlatformViewsController
XCTAssertTrue([flutterPlatformViewsController submitFrame:std::move(mock_surface) submitFrame:std::move(mock_surface)
withIosContext:nil withIosContext:std::make_shared<flutter::IOSContextNoop>()
grContext:nil]); grContext:nil]);
XCTAssertTrue([flutterView.subviews indexOfObject:clippingView1] < XCTAssertTrue([flutterView.subviews indexOfObject:clippingView1] <
@ -3945,9 +3951,9 @@ fml::RefPtr<fml::TaskRunner> GetDefaultTaskRunner() {
[](const flutter::SurfaceFrame& surface_frame, flutter::DlCanvas* canvas) { return true; }, [](const flutter::SurfaceFrame& surface_frame, flutter::DlCanvas* canvas) { return true; },
[](const flutter::SurfaceFrame& surface_frame) { return true; }, [](const flutter::SurfaceFrame& surface_frame) { return true; },
/*frame_size=*/SkISize::Make(800, 600)); /*frame_size=*/SkISize::Make(800, 600));
XCTAssertTrue([flutterPlatformViewsController
XCTAssertTrue([flutterPlatformViewsController submitFrame:std::move(mock_surface) submitFrame:std::move(mock_surface)
withIosContext:nil withIosContext:std::make_shared<flutter::IOSContextNoop>()
grContext:nil]); grContext:nil]);
// Disposing won't remove embedded views until the view is removed from the composition_order_ // Disposing won't remove embedded views until the view is removed from the composition_order_
@ -3975,9 +3981,9 @@ fml::RefPtr<fml::TaskRunner> GetDefaultTaskRunner() {
[](const flutter::SurfaceFrame& surface_frame, flutter::DlCanvas* canvas) { return true; }, [](const flutter::SurfaceFrame& surface_frame, flutter::DlCanvas* canvas) { return true; },
[](const flutter::SurfaceFrame& surface_frame) { return true; }, [](const flutter::SurfaceFrame& surface_frame) { return true; },
/*frame_size=*/SkISize::Make(800, 600)); /*frame_size=*/SkISize::Make(800, 600));
XCTAssertTrue([flutterPlatformViewsController
XCTAssertTrue([flutterPlatformViewsController submitFrame:std::move(mock_surface) submitFrame:std::move(mock_surface)
withIosContext:nil withIosContext:std::make_shared<flutter::IOSContextNoop>()
grContext:nil]); grContext:nil]);
// Disposing won't remove embedded views until the view is removed from the composition_order_ // Disposing won't remove embedded views until the view is removed from the composition_order_
@ -4051,9 +4057,8 @@ fml::RefPtr<fml::TaskRunner> GetDefaultTaskRunner() {
[](const flutter::SurfaceFrame& surface_frame, flutter::DlCanvas* canvas) { return true; }, [](const flutter::SurfaceFrame& surface_frame, flutter::DlCanvas* canvas) { return true; },
[](const flutter::SurfaceFrame& surface_frame) { return true; }, [](const flutter::SurfaceFrame& surface_frame) { return true; },
/*frame_size=*/SkISize::Make(800, 600)); /*frame_size=*/SkISize::Make(800, 600));
[flutterPlatformViewsController submitFrame:std::move(mock_surface) [flutterPlatformViewsController submitFrame:std::move(mock_surface)
withIosContext:nil withIosContext:std::make_shared<flutter::IOSContextNoop>()
grContext:nil]; grContext:nil];
UIView* someView = [[UIView alloc] init]; UIView* someView = [[UIView alloc] init];
@ -4130,9 +4135,8 @@ fml::RefPtr<fml::TaskRunner> GetDefaultTaskRunner() {
[](const flutter::SurfaceFrame& surface_frame, flutter::DlCanvas* canvas) { return true; }, [](const flutter::SurfaceFrame& surface_frame, flutter::DlCanvas* canvas) { return true; },
[](const flutter::SurfaceFrame& surface_frame) { return true; }, [](const flutter::SurfaceFrame& surface_frame) { return true; },
/*frame_size=*/SkISize::Make(800, 600)); /*frame_size=*/SkISize::Make(800, 600));
[flutterPlatformViewsController submitFrame:std::move(mock_surface) [flutterPlatformViewsController submitFrame:std::move(mock_surface)
withIosContext:nil withIosContext:std::make_shared<flutter::IOSContextNoop>()
grContext:nil]; grContext:nil];
XCTAssertEqual(flutterView.subviews.count, 1u); XCTAssertEqual(flutterView.subviews.count, 1u);
@ -4252,7 +4256,7 @@ fml::RefPtr<fml::TaskRunner> GetDefaultTaskRunner() {
}); });
[flutterPlatformViewsController submitFrame:std::move(mock_surface) [flutterPlatformViewsController submitFrame:std::move(mock_surface)
withIosContext:nil withIosContext:std::make_shared<flutter::IOSContextNoop>()
grContext:nil]; grContext:nil];
XCTAssertTrue(submit_info.has_value()); XCTAssertTrue(submit_info.has_value());