Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit eb5c6f0

Browse files
authored
iOS FlutterTextureRegistry should be a proxy, not the engine itself (#37666)
* feat: add texture registry relay. * fix: add test. * fix: format * fix: add comment. * fix: remove useless import. * fix: remove * fix: file name order. * fix. * add test for retain cycle. * fix compile * Add comments. * remove relay. * add FlutterTextureRegistryRelay in gn * add golden files. * add * add comments.
1 parent 5df0072 commit eb5c6f0

File tree

8 files changed

+163
-6
lines changed

8 files changed

+163
-6
lines changed

ci/licenses_golden/licenses_flutter

+6
Original file line numberDiff line numberDiff line change
@@ -2519,6 +2519,9 @@ ORIGIN: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterTextI
25192519
ORIGIN: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterTextInputPlugin.h + ../../../flutter/LICENSE
25202520
ORIGIN: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterTextInputPlugin.mm + ../../../flutter/LICENSE
25212521
ORIGIN: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterTextInputPluginTest.mm + ../../../flutter/LICENSE
2522+
ORIGIN: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterTextureRegistryRelay.h + ../../../flutter/LICENSE
2523+
ORIGIN: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterTextureRegistryRelay.mm + ../../../flutter/LICENSE
2524+
ORIGIN: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterTextureRegistryRelayTest.mm + ../../../flutter/LICENSE
25222525
ORIGIN: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterUIPressProxy.h + ../../../flutter/LICENSE
25232526
ORIGIN: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterUIPressProxy.mm + ../../../flutter/LICENSE
25242527
ORIGIN: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterUmbrellaImport.m + ../../../flutter/LICENSE
@@ -5000,6 +5003,9 @@ FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterTextInp
50005003
FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterTextInputPlugin.h
50015004
FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterTextInputPlugin.mm
50025005
FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterTextInputPluginTest.mm
5006+
FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterTextureRegistryRelay.h
5007+
FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterTextureRegistryRelay.mm
5008+
FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterTextureRegistryRelayTest.mm
50035009
FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterUIPressProxy.h
50045010
FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterUIPressProxy.mm
50055011
FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterUmbrellaImport.m

shell/platform/darwin/ios/BUILD.gn

+3
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,8 @@ source_set("flutter_framework_source") {
106106
"framework/Source/FlutterSemanticsScrollView.mm",
107107
"framework/Source/FlutterSpellCheckPlugin.h",
108108
"framework/Source/FlutterSpellCheckPlugin.mm",
109+
"framework/Source/FlutterTextureRegistryRelay.h",
110+
"framework/Source/FlutterTextureRegistryRelay.mm",
109111
"framework/Source/FlutterUIPressProxy.h",
110112
"framework/Source/FlutterUIPressProxy.mm",
111113
"framework/Source/FlutterUndoManagerDelegate.h",
@@ -282,6 +284,7 @@ shared_library("ios_test_flutter") {
282284
"framework/Source/FlutterRestorationPluginTest.mm",
283285
"framework/Source/FlutterSpellCheckPluginTest.mm",
284286
"framework/Source/FlutterTextInputPluginTest.mm",
287+
"framework/Source/FlutterTextureRegistryRelayTest.mm",
285288
"framework/Source/FlutterUndoManagerPluginTest.mm",
286289
"framework/Source/FlutterViewControllerTest.mm",
287290
"framework/Source/SemanticsObjectTest.mm",

shell/platform/darwin/ios/framework/Headers/FlutterEngine.h

+6-1
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ extern NSString* const FlutterDefaultInitialRoute;
5656
* One of these methods must be invoked before calling `-setViewController:`.
5757
*/
5858
FLUTTER_DARWIN_EXPORT
59-
@interface FlutterEngine : NSObject <FlutterTextureRegistry, FlutterPluginRegistry>
59+
@interface FlutterEngine : NSObject <FlutterPluginRegistry>
6060

6161
/**
6262
* Default initializer for a FlutterEngine.
@@ -424,6 +424,11 @@ FLUTTER_DARWIN_EXPORT
424424
*/
425425
@property(nonatomic, readonly) NSObject<FlutterBinaryMessenger>* binaryMessenger;
426426

427+
/**
428+
* The `FlutterTextureRegistry` associated with this FlutterEngine (used to register textures).
429+
*/
430+
@property(nonatomic, readonly) NSObject<FlutterTextureRegistry>* textureRegistry;
431+
427432
/**
428433
* The UI Isolate ID of the engine.
429434
*

shell/platform/darwin/ios/framework/Source/FlutterEngine.mm

+13-2
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#import "flutter/shell/platform/darwin/ios/framework/Source/FlutterPlatformPlugin.h"
2727
#import "flutter/shell/platform/darwin/ios/framework/Source/FlutterSpellCheckPlugin.h"
2828
#import "flutter/shell/platform/darwin/ios/framework/Source/FlutterTextInputDelegate.h"
29+
#import "flutter/shell/platform/darwin/ios/framework/Source/FlutterTextureRegistryRelay.h"
2930
#import "flutter/shell/platform/darwin/ios/framework/Source/FlutterUndoManagerDelegate.h"
3031
#import "flutter/shell/platform/darwin/ios/framework/Source/FlutterUndoManagerPlugin.h"
3132
#import "flutter/shell/platform/darwin/ios/framework/Source/FlutterViewController_Internal.h"
@@ -87,7 +88,8 @@ - (instancetype)initWithPlugin:(NSString*)pluginKey flutterEngine:(FlutterEngine
8788
@interface FlutterEngine () <FlutterIndirectScribbleDelegate,
8889
FlutterUndoManagerDelegate,
8990
FlutterTextInputDelegate,
90-
FlutterBinaryMessenger>
91+
FlutterBinaryMessenger,
92+
FlutterTextureRegistry>
9193
// Maintains a dictionary of plugin names that have registered with the engine. Used by
9294
// FlutterEngineRegistrar to implement a FlutterPluginRegistrar.
9395
@property(nonatomic, readonly) NSMutableDictionary* pluginPublications;
@@ -138,6 +140,7 @@ @implementation FlutterEngine {
138140
BOOL _allowHeadlessExecution;
139141
BOOL _restorationEnabled;
140142
FlutterBinaryMessengerRelay* _binaryMessenger;
143+
FlutterTextureRegistryRelay* _textureRegistry;
141144
std::unique_ptr<flutter::ConnectionCollection> _connections;
142145
}
143146

@@ -197,6 +200,7 @@ - (instancetype)initWithName:(NSString*)labelPrefix
197200
[self recreatePlatformViewController];
198201

199202
_binaryMessenger = [[FlutterBinaryMessengerRelay alloc] initWithParent:self];
203+
_textureRegistry = [[FlutterTextureRegistryRelay alloc] initWithParent:self];
200204
_connections.reset(new flutter::ConnectionCollection());
201205

202206
NSNotificationCenter* center = [NSNotificationCenter defaultCenter];
@@ -261,7 +265,10 @@ - (void)dealloc {
261265
[_pluginPublications release];
262266
[_registrars release];
263267
_binaryMessenger.parent = nil;
268+
_textureRegistry.parent = nil;
264269
[_binaryMessenger release];
270+
[_textureRegistry release];
271+
_textureRegistry = nil;
265272
[_isolateId release];
266273

267274
NSNotificationCenter* center = [NSNotificationCenter defaultCenter];
@@ -1073,6 +1080,10 @@ - (void)flutterViewAccessibilityDidCall {
10731080
return _binaryMessenger;
10741081
}
10751082

1083+
- (NSObject<FlutterTextureRegistry>*)textureRegistry {
1084+
return _textureRegistry;
1085+
}
1086+
10761087
// For test only. Ideally we should create a dependency injector for all dependencies and
10771088
// remove this.
10781089
- (void)setBinaryMessenger:(FlutterBinaryMessengerRelay*)binaryMessenger {
@@ -1333,7 +1344,7 @@ - (void)dealloc {
13331344
}
13341345

13351346
- (NSObject<FlutterTextureRegistry>*)textures {
1336-
return _flutterEngine;
1347+
return _flutterEngine.textureRegistry;
13371348
}
13381349

13391350
- (void)publish:(NSObject*)value {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// Copyright 2013 The Flutter Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
#import "flutter/shell/platform/darwin/common/framework/Headers/FlutterMacros.h"
6+
#import "flutter/shell/platform/darwin/common/framework/Headers/FlutterTexture.h"
7+
8+
#if FLUTTER_RUNTIME_MODE == FLUTTER_RUNTIME_MODE_DEBUG
9+
FLUTTER_DARWIN_EXPORT
10+
#endif
11+
12+
/**
13+
* Wrapper around a weakly held collection of registered textures.
14+
*
15+
* Avoids a retain cycle between plugins and the engine.
16+
*/
17+
@interface FlutterTextureRegistryRelay : NSObject <FlutterTextureRegistry>
18+
19+
/**
20+
* A weak reference to a FlutterEngine that will be passed texture registration.
21+
*/
22+
@property(nonatomic, assign) NSObject<FlutterTextureRegistry>* parent;
23+
- (instancetype)initWithParent:(NSObject<FlutterTextureRegistry>*)parent;
24+
@end
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
// Copyright 2013 The Flutter Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
#import "flutter/shell/platform/darwin/ios/framework/Source/FlutterTextureRegistryRelay.h"
6+
7+
#include "flutter/fml/logging.h"
8+
9+
@implementation FlutterTextureRegistryRelay : NSObject
10+
11+
#pragma mark - FlutterTextureRegistry
12+
13+
- (instancetype)initWithParent:(NSObject<FlutterTextureRegistry>*)parent {
14+
if (self = [super init]) {
15+
_parent = parent;
16+
}
17+
return self;
18+
}
19+
20+
- (int64_t)registerTexture:(NSObject<FlutterTexture>*)texture {
21+
if (!self.parent) {
22+
FML_LOG(WARNING) << "Using on an empty registry.";
23+
return 0;
24+
}
25+
return [self.parent registerTexture:texture];
26+
}
27+
28+
- (void)textureFrameAvailable:(int64_t)textureId {
29+
if (!self.parent) {
30+
FML_LOG(WARNING) << "Using on an empty registry.";
31+
}
32+
return [self.parent textureFrameAvailable:textureId];
33+
}
34+
35+
- (void)unregisterTexture:(int64_t)textureId {
36+
if (!self.parent) {
37+
FML_LOG(WARNING) << "Using on an empty registry.";
38+
}
39+
return [self.parent unregisterTexture:textureId];
40+
}
41+
42+
@end
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
// Copyright 2013 The Flutter Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
#import "flutter/shell/platform/darwin/ios/framework/Headers/FlutterEngine.h"
6+
#import "flutter/shell/platform/darwin/ios/framework/Source/FlutterTextureRegistryRelay.h"
7+
8+
#import <OCMock/OCMock.h>
9+
#import <XCTest/XCTest.h>
10+
11+
#import "flutter/shell/platform/darwin/common/framework/Headers/FlutterMacros.h"
12+
#import "flutter/shell/platform/darwin/common/framework/Headers/FlutterTexture.h"
13+
14+
FLUTTER_ASSERT_ARC
15+
16+
@interface FlutterTextureRegistryRelayTest : XCTestCase
17+
@end
18+
19+
@implementation FlutterTextureRegistryRelayTest
20+
21+
- (void)testCreate {
22+
id textureRegistry = OCMProtocolMock(@protocol(FlutterTextureRegistry));
23+
FlutterTextureRegistryRelay* relay =
24+
[[FlutterTextureRegistryRelay alloc] initWithParent:textureRegistry];
25+
XCTAssertNotNil(relay);
26+
XCTAssertEqual(textureRegistry, relay.parent);
27+
}
28+
29+
- (void)testRegisterTexture {
30+
id textureRegistry = OCMProtocolMock(@protocol(FlutterTextureRegistry));
31+
FlutterTextureRegistryRelay* relay =
32+
[[FlutterTextureRegistryRelay alloc] initWithParent:textureRegistry];
33+
id texture = OCMProtocolMock(@protocol(FlutterTexture));
34+
[relay registerTexture:texture];
35+
OCMVerify([textureRegistry registerTexture:texture]);
36+
}
37+
38+
- (void)testTextureFrameAvailable {
39+
id textureRegistry = OCMProtocolMock(@protocol(FlutterTextureRegistry));
40+
FlutterTextureRegistryRelay* relay =
41+
[[FlutterTextureRegistryRelay alloc] initWithParent:textureRegistry];
42+
[relay textureFrameAvailable:0];
43+
OCMVerify([textureRegistry textureFrameAvailable:0]);
44+
}
45+
46+
- (void)testUnregisterTexture {
47+
id textureRegistry = OCMProtocolMock(@protocol(FlutterTextureRegistry));
48+
FlutterTextureRegistryRelay* relay =
49+
[[FlutterTextureRegistryRelay alloc] initWithParent:textureRegistry];
50+
[relay unregisterTexture:0];
51+
OCMVerify([textureRegistry unregisterTexture:0]);
52+
}
53+
54+
- (void)testRetainCycle {
55+
__weak FlutterEngine* weakEngine;
56+
NSObject<FlutterTextureRegistry>* strongRelay;
57+
@autoreleasepool {
58+
id project = OCMClassMock([FlutterDartProject class]);
59+
FlutterEngine* engine = [[FlutterEngine alloc] initWithName:@"foobar" project:project];
60+
strongRelay = [engine textureRegistry];
61+
weakEngine = engine;
62+
}
63+
XCTAssertNil(weakEngine);
64+
}
65+
66+
@end

shell/platform/darwin/ios/framework/Source/FlutterViewController.mm

+3-3
Original file line numberDiff line numberDiff line change
@@ -2022,15 +2022,15 @@ - (void)cleanUpConnection:(FlutterBinaryMessengerConnection)connection {
20222022
#pragma mark - FlutterTextureRegistry
20232023

20242024
- (int64_t)registerTexture:(NSObject<FlutterTexture>*)texture {
2025-
return [_engine.get() registerTexture:texture];
2025+
return [_engine.get().textureRegistry registerTexture:texture];
20262026
}
20272027

20282028
- (void)unregisterTexture:(int64_t)textureId {
2029-
[_engine.get() unregisterTexture:textureId];
2029+
[_engine.get().textureRegistry unregisterTexture:textureId];
20302030
}
20312031

20322032
- (void)textureFrameAvailable:(int64_t)textureId {
2033-
[_engine.get() textureFrameAvailable:textureId];
2033+
[_engine.get().textureRegistry textureFrameAvailable:textureId];
20342034
}
20352035

20362036
- (NSString*)lookupKeyForAsset:(NSString*)asset {

0 commit comments

Comments
 (0)