| Flutter iOS Embedder |

FlutterPlatformPluginTest.mm
Go to the documentation of this file.
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 <OCMock/OCMock.h>
6 #import <XCTest/XCTest.h>
7
8 #import "flutter/shell/platform/darwin/common/framework/Headers/FlutterBinaryMessenger.h"
9 #import "flutter/shell/platform/darwin/common/framework/Headers/FlutterMacros.h"
10 #import "flutter/shell/platform/darwin/ios/framework/Headers/FlutterViewController.h"
11 #import "flutter/shell/platform/darwin/ios/framework/Source/FlutterEngine_Internal.h"
12 #import "flutter/shell/platform/darwin/ios/framework/Source/FlutterPlatformPlugin.h"
13 #import "flutter/shell/platform/darwin/ios/platform_view_ios.h"
14
15 FLUTTER_ASSERT_ARC
16
17 @interface FlutterPlatformPluginTest : XCTestCase
18 @end
19
20 @interface FlutterPlatformPlugin ()
21 - (BOOL)isLiveTextInputAvailable;
22 - (void)searchWeb:(NSString*)searchTerm;
23 - (void)showLookUpViewController:(NSString*)term;
24 - (void)showShareViewController:(NSString*)content;
25 @end
26
27 @interface UIViewController ()
28 - (void)presentViewController:(UIViewController*)viewControllerToPresent
29 animated:(BOOL)flag
30 completion:(void (^)(void))completion;
31 @end
32
33 @implementation FlutterPlatformPluginTest
34 - (void)testSearchWebInvokedWithEscapedTerm {
35 id mockApplication = OCMClassMock([UIApplication class]);
36 OCMStub([mockApplication sharedApplication]).andReturn(mockApplication);
37
38 FlutterEngine* engine = [[FlutterEngine alloc] initWithName:@"test" project:nil];
39 [engine runWithEntrypoint:nil];
40
41 XCTestExpectation* invokeExpectation =
42 [self expectationWithDescription:@"Web search launched with escaped search term"];
43
44 FlutterPlatformPlugin* plugin = [[FlutterPlatformPlugin alloc] initWithEngine:engine];
45 FlutterPlatformPlugin* mockPlugin = OCMPartialMock(plugin);
46
47 FlutterMethodCall* methodCall = [FlutterMethodCall methodCallWithMethodName:@"SearchWeb.invoke"
48 arguments:@"Testing Word!"];
49
50 FlutterResult result = ^(id result) {
51 OCMVerify([mockPlugin searchWeb:@"Testing Word!"]);
52 #if not APPLICATION_EXTENSION_API_ONLY
53 OCMVerify([mockApplication openURL:[NSURL URLWithString:@"x-web-search://?Testing%20Word!"]
54 options:@{}
55 completionHandler:nil]);
56 #endif
57 [invokeExpectation fulfill];
58 };
59
60 [mockPlugin handleMethodCall:methodCall result:result];
61 [self waitForExpectationsWithTimeout:1 handler:nil];
62 [mockApplication stopMocking];
63 }
64
65 - (void)testSearchWebInvokedWithNonEscapedTerm {
66 id mockApplication = OCMClassMock([UIApplication class]);
67 OCMStub([mockApplication sharedApplication]).andReturn(mockApplication);
68
69 FlutterEngine* engine = [[FlutterEngine alloc] initWithName:@"test" project:nil];
70 [engine runWithEntrypoint:nil];
71
72 XCTestExpectation* invokeExpectation =
73 [self expectationWithDescription:@"Web search launched with non escaped search term"];
74
75 FlutterPlatformPlugin* plugin = [[FlutterPlatformPlugin alloc] initWithEngine:engine];
76 FlutterPlatformPlugin* mockPlugin = OCMPartialMock(plugin);
77
78 FlutterMethodCall* methodCall = [FlutterMethodCall methodCallWithMethodName:@"SearchWeb.invoke"
79 arguments:@"Test"];
80
81 FlutterResult result = ^(id result) {
82 OCMVerify([mockPlugin searchWeb:@"Test"]);
83 #if not APPLICATION_EXTENSION_API_ONLY
84 OCMVerify([mockApplication openURL:[NSURL URLWithString:@"x-web-search://?Test"]
85 options:@{}
86 completionHandler:nil]);
87 #endif
88 [invokeExpectation fulfill];
89 };
90
91 [mockPlugin handleMethodCall:methodCall result:result];
92 [self waitForExpectationsWithTimeout:1 handler:nil];
93 [mockApplication stopMocking];
94 }
95
96 - (void)testLookUpCallInitiated {
97 FlutterEngine* engine = [[FlutterEngine alloc] initWithName:@"test" project:nil];
98 [engine runWithEntrypoint:nil];
99
100 XCTestExpectation* presentExpectation =
101 [self expectationWithDescription:@"Look Up view controller presented"];
102
103 FlutterViewController* engineViewController = [[FlutterViewController alloc] initWithEngine:engine
104 nibName:nil
105 bundle:nil];
106 FlutterViewController* mockEngineViewController = OCMPartialMock(engineViewController);
107
108 FlutterPlatformPlugin* plugin = [[FlutterPlatformPlugin alloc] initWithEngine:engine];
109 FlutterPlatformPlugin* mockPlugin = OCMPartialMock(plugin);
110
111 FlutterMethodCall* methodCall = [FlutterMethodCall methodCallWithMethodName:@"LookUp.invoke"
112 arguments:@"Test"];
113 FlutterResult result = ^(id result) {
114 OCMVerify([mockEngineViewController
115 presentViewController:[OCMArg isKindOfClass:[UIReferenceLibraryViewController class]]
116 animated:YES
117 completion:nil]);
118 [presentExpectation fulfill];
119 };
120 [mockPlugin handleMethodCall:methodCall result:result];
121 [self waitForExpectationsWithTimeout:2 handler:nil];
122 }
123
124 - (void)testShareScreenInvoked {
125 FlutterEngine* engine = [[FlutterEngine alloc] initWithName:@"test" project:nil];
126 [engine runWithEntrypoint:nil];
127
128 XCTestExpectation* presentExpectation =
129 [self expectationWithDescription:@"Share view controller presented"];
130
131 FlutterViewController* engineViewController = [[FlutterViewController alloc] initWithEngine:engine
132 nibName:nil
133 bundle:nil];
134 FlutterViewController* mockEngineViewController = OCMPartialMock(engineViewController);
135 OCMStub([mockEngineViewController
136 presentViewController:[OCMArg isKindOfClass:[UIActivityViewController class]]
137 animated:YES
138 completion:nil]);
139
140 FlutterPlatformPlugin* plugin = [[FlutterPlatformPlugin alloc] initWithEngine:engine];
141 FlutterPlatformPlugin* mockPlugin = OCMPartialMock(plugin);
142
143 FlutterMethodCall* methodCall = [FlutterMethodCall methodCallWithMethodName:@"Share.invoke"
144 arguments:@"Test"];
145 FlutterResult result = ^(id result) {
146 OCMVerify([mockEngineViewController
147 presentViewController:[OCMArg isKindOfClass:[UIActivityViewController class]]
148 animated:YES
149 completion:nil]);
150 [presentExpectation fulfill];
151 };
152 [mockPlugin handleMethodCall:methodCall result:result];
153 [self waitForExpectationsWithTimeout:1 handler:nil];
154 }
155
156 - (void)testShareScreenInvokedOnIPad {
157 FlutterEngine* engine = [[FlutterEngine alloc] initWithName:@"test" project:nil];
158 [engine runWithEntrypoint:nil];
159
160 XCTestExpectation* presentExpectation =
161 [self expectationWithDescription:@"Share view controller presented on iPad"];
162
163 FlutterViewController* engineViewController = [[FlutterViewController alloc] initWithEngine:engine
164 nibName:nil
165 bundle:nil];
166 FlutterViewController* mockEngineViewController = OCMPartialMock(engineViewController);
167 OCMStub([mockEngineViewController
168 presentViewController:[OCMArg isKindOfClass:[UIActivityViewController class]]
169 animated:YES
170 completion:nil]);
171
172 id mockTraitCollection = OCMClassMock([UITraitCollection class]);
173 OCMStub([mockTraitCollection userInterfaceIdiom]).andReturn(UIUserInterfaceIdiomPad);
174
175 FlutterPlatformPlugin* plugin = [[FlutterPlatformPlugin alloc] initWithEngine:engine];
176 FlutterPlatformPlugin* mockPlugin = OCMPartialMock(plugin);
177
178 FlutterMethodCall* methodCall = [FlutterMethodCall methodCallWithMethodName:@"Share.invoke"
179 arguments:@"Test"];
180 FlutterResult result = ^(id result) {
181 OCMVerify([mockEngineViewController
182 presentViewController:[OCMArg isKindOfClass:[UIActivityViewController class]]
183 animated:YES
184 completion:nil]);
185 [presentExpectation fulfill];
186 };
187 [mockPlugin handleMethodCall:methodCall result:result];
188 [self waitForExpectationsWithTimeout:1 handler:nil];
189 }
190
191 - (void)testClipboardHasCorrectStrings {
192 [UIPasteboard generalPasteboard].string = nil;
193 FlutterEngine* engine = [[FlutterEngine alloc] initWithName:@"test" project:nil];
194 FlutterPlatformPlugin* plugin = [[FlutterPlatformPlugin alloc] initWithEngine:engine];
195
196 XCTestExpectation* setStringExpectation = [self expectationWithDescription:@"setString"];
197 FlutterResult resultSet = ^(id result) {
198 [setStringExpectation fulfill];
199 };
200 FlutterMethodCall* methodCallSet =
201 [FlutterMethodCall methodCallWithMethodName:@"Clipboard.setData"
202 arguments:@{@"text" : @"some string"}];
203 [plugin handleMethodCall:methodCallSet result:resultSet];
204 [self waitForExpectationsWithTimeout:1 handler:nil];
205
206 XCTestExpectation* hasStringsExpectation = [self expectationWithDescription:@"hasStrings"];
207 FlutterResult result = ^(id result) {
208 XCTAssertTrue([result[@"value"] boolValue]);
209 [hasStringsExpectation fulfill];
210 };
211 FlutterMethodCall* methodCall =
212 [FlutterMethodCall methodCallWithMethodName:@"Clipboard.hasStrings" arguments:nil];
213 [plugin handleMethodCall:methodCall result:result];
214 [self waitForExpectationsWithTimeout:1 handler:nil];
215
216 XCTestExpectation* getDataExpectation = [self expectationWithDescription:@"getData"];
217 FlutterResult getDataResult = ^(id result) {
218 XCTAssertEqualObjects(result[@"text"], @"some string");
219 [getDataExpectation fulfill];
220 };
221 FlutterMethodCall* methodCallGetData =
222 [FlutterMethodCall methodCallWithMethodName:@"Clipboard.getData" arguments:@"text/plain"];
223 [plugin handleMethodCall:methodCallGetData result:getDataResult];
224 [self waitForExpectationsWithTimeout:1 handler:nil];
225 }
226
227 - (void)testClipboardSetDataToNullDoNotCrash {
228 [UIPasteboard generalPasteboard].string = nil;
229 FlutterEngine* engine = [[FlutterEngine alloc] initWithName:@"test" project:nil];
230 FlutterPlatformPlugin* plugin = [[FlutterPlatformPlugin alloc] initWithEngine:engine];
231
232 XCTestExpectation* setStringExpectation = [self expectationWithDescription:@"setData"];
233 FlutterResult resultSet = ^(id result) {
234 [setStringExpectation fulfill];
235 };
236 FlutterMethodCall* methodCallSet =
237 [FlutterMethodCall methodCallWithMethodName:@"Clipboard.setData"
238 arguments:@{@"text" : [NSNull null]}];
239 [plugin handleMethodCall:methodCallSet result:resultSet];
240
241 XCTestExpectation* getDataExpectation = [self expectationWithDescription:@"getData"];
242 FlutterResult result = ^(id result) {
243 XCTAssertEqualObjects(result[@"text"], @"null");
244 [getDataExpectation fulfill];
245 };
246 FlutterMethodCall* methodCall = [FlutterMethodCall methodCallWithMethodName:@"Clipboard.getData"
247 arguments:@"text/plain"];
248 [plugin handleMethodCall:methodCall result:result];
249 [self waitForExpectationsWithTimeout:1 handler:nil];
250 }
251
252 - (void)testPopSystemNavigator {
253 FlutterEngine* engine = [[FlutterEngine alloc] initWithName:@"test" project:nil];
254 [engine runWithEntrypoint:nil];
255 FlutterViewController* flutterViewController =
256 [[FlutterViewController alloc] initWithEngine:engine nibName:nil bundle:nil];
257 UINavigationController* navigationController =
258 [[UINavigationController alloc] initWithRootViewController:flutterViewController];
259 UITabBarController* tabBarController = [[UITabBarController alloc] init];
260 tabBarController.viewControllers = @[ navigationController ];
261 FlutterPlatformPlugin* plugin = [[FlutterPlatformPlugin alloc] initWithEngine:engine];
262
263 id navigationControllerMock = OCMPartialMock(navigationController);
264 OCMStub([navigationControllerMock popViewControllerAnimated:YES]);
265 // Set some string to the pasteboard.
266 XCTestExpectation* navigationPopCalled = [self expectationWithDescription:@"SystemNavigator.pop"];
267 FlutterResult resultSet = ^(id result) {
268 [navigationPopCalled fulfill];
269 };
270 FlutterMethodCall* methodCallSet =
271 [FlutterMethodCall methodCallWithMethodName:@"SystemNavigator.pop" arguments:@(YES)];
272 [plugin handleMethodCall:methodCallSet result:resultSet];
273 [self waitForExpectationsWithTimeout:1 handler:nil];
274 OCMVerify([navigationControllerMock popViewControllerAnimated:YES]);
275
276 [flutterViewController deregisterNotifications];
277 }
278
279 - (void)testWhetherDeviceHasLiveTextInputInvokeCorrectly {
280 FlutterEngine* engine = [[FlutterEngine alloc] initWithName:@"test" project:nil];
281 XCTestExpectation* invokeExpectation =
282 [self expectationWithDescription:@"isLiveTextInputAvailableInvoke"];
283 FlutterPlatformPlugin* plugin = [[FlutterPlatformPlugin alloc] initWithEngine:engine];
284 FlutterPlatformPlugin* mockPlugin = OCMPartialMock(plugin);
285 FlutterMethodCall* methodCall =
286 [FlutterMethodCall methodCallWithMethodName:@"LiveText.isLiveTextInputAvailable"
287 arguments:nil];
288 FlutterResult result = ^(id result) {
289 OCMVerify([mockPlugin isLiveTextInputAvailable]);
290 [invokeExpectation fulfill];
291 };
292 [mockPlugin handleMethodCall:methodCall result:result];
293 [self waitForExpectationsWithTimeout:1 handler:nil];
294 }
295
296 - (void)testViewControllerBasedStatusBarHiddenUpdate {
297 id bundleMock = OCMPartialMock([NSBundle mainBundle]);
298 OCMStub([bundleMock objectForInfoDictionaryKey:@"UIViewControllerBasedStatusBarAppearance"])
299 .andReturn(@YES);
300 {
301 // Enabling system UI overlays to update status bar.
302 FlutterEngine* engine = [[FlutterEngine alloc] initWithName:@"test" project:nil];
303 [engine runWithEntrypoint:nil];
304 FlutterViewController* flutterViewController =
305 [[FlutterViewController alloc] initWithEngine:engine nibName:nil bundle:nil];
306 XCTAssertFalse(flutterViewController.prefersStatusBarHidden);
307
308 // Update to hidden.
309 FlutterPlatformPlugin* plugin = [engine platformPlugin];
310
311 XCTestExpectation* enableSystemUIOverlaysCalled =
312 [self expectationWithDescription:@"setEnabledSystemUIOverlays"];
313 FlutterResult resultSet = ^(id result) {
314 [enableSystemUIOverlaysCalled fulfill];
315 };
316 FlutterMethodCall* methodCallSet =
317 [FlutterMethodCall methodCallWithMethodName:@"SystemChrome.setEnabledSystemUIOverlays"
318 arguments:@[ @"SystemUiOverlay.bottom" ]];
319 [plugin handleMethodCall:methodCallSet result:resultSet];
320 [self waitForExpectationsWithTimeout:1 handler:nil];
321 XCTAssertTrue(flutterViewController.prefersStatusBarHidden);
322
323 // Update to shown.
324 XCTestExpectation* enableSystemUIOverlaysCalled2 =
325 [self expectationWithDescription:@"setEnabledSystemUIOverlays"];
326 FlutterResult resultSet2 = ^(id result) {
327 [enableSystemUIOverlaysCalled2 fulfill];
328 };
329 FlutterMethodCall* methodCallSet2 =
330 [FlutterMethodCall methodCallWithMethodName:@"SystemChrome.setEnabledSystemUIOverlays"
331 arguments:@[ @"SystemUiOverlay.top" ]];
332 [plugin handleMethodCall:methodCallSet2 result:resultSet2];
333 [self waitForExpectationsWithTimeout:1 handler:nil];
334 XCTAssertFalse(flutterViewController.prefersStatusBarHidden);
335
336 [flutterViewController deregisterNotifications];
337 }
338 {
339 // Enable system UI mode to update status bar.
340 FlutterEngine* engine = [[FlutterEngine alloc] initWithName:@"test" project:nil];
341 [engine runWithEntrypoint:nil];
342 FlutterViewController* flutterViewController =
343 [[FlutterViewController alloc] initWithEngine:engine nibName:nil bundle:nil];
344 XCTAssertFalse(flutterViewController.prefersStatusBarHidden);
345
346 // Update to hidden.
347 FlutterPlatformPlugin* plugin = [engine platformPlugin];
348
349 XCTestExpectation* enableSystemUIModeCalled =
350 [self expectationWithDescription:@"setEnabledSystemUIMode"];
351 FlutterResult resultSet = ^(id result) {
352 [enableSystemUIModeCalled fulfill];
353 };
354 FlutterMethodCall* methodCallSet =
355 [FlutterMethodCall methodCallWithMethodName:@"SystemChrome.setEnabledSystemUIMode"
356 arguments:@"SystemUiMode.immersive"];
357 [plugin handleMethodCall:methodCallSet result:resultSet];
358 [self waitForExpectationsWithTimeout:1 handler:nil];
359 XCTAssertTrue(flutterViewController.prefersStatusBarHidden);
360
361 // Update to shown.
362 XCTestExpectation* enableSystemUIModeCalled2 =
363 [self expectationWithDescription:@"setEnabledSystemUIMode"];
364 FlutterResult resultSet2 = ^(id result) {
365 [enableSystemUIModeCalled2 fulfill];
366 };
367 FlutterMethodCall* methodCallSet2 =
368 [FlutterMethodCall methodCallWithMethodName:@"SystemChrome.setEnabledSystemUIMode"
369 arguments:@"SystemUiMode.edgeToEdge"];
370 [plugin handleMethodCall:methodCallSet2 result:resultSet2];
371 [self waitForExpectationsWithTimeout:1 handler:nil];
372 XCTAssertFalse(flutterViewController.prefersStatusBarHidden);
373
374 [flutterViewController deregisterNotifications];
375 }
376 [bundleMock stopMocking];
377 }
378
379 - (void)testStatusBarHiddenUpdate {
380 id bundleMock = OCMPartialMock([NSBundle mainBundle]);
381 OCMStub([bundleMock objectForInfoDictionaryKey:@"UIViewControllerBasedStatusBarAppearance"])
382 .andReturn(@NO);
383 id mockApplication = OCMClassMock([UIApplication class]);
384 OCMStub([mockApplication sharedApplication]).andReturn(mockApplication);
385
386 // Enabling system UI overlays to update status bar.
387 FlutterEngine* engine = [[FlutterEngine alloc] initWithName:@"test" project:nil];
388 [engine runWithEntrypoint:nil];
389 FlutterViewController* flutterViewController =
390 [[FlutterViewController alloc] initWithEngine:engine nibName:nil bundle:nil];
391
392 // Update to hidden.
393 FlutterPlatformPlugin* plugin = [engine platformPlugin];
394
395 XCTestExpectation* enableSystemUIOverlaysCalled =
396 [self expectationWithDescription:@"setEnabledSystemUIOverlays"];
397 FlutterResult resultSet = ^(id result) {
398 [enableSystemUIOverlaysCalled fulfill];
399 };
400 FlutterMethodCall* methodCallSet =
401 [FlutterMethodCall methodCallWithMethodName:@"SystemChrome.setEnabledSystemUIOverlays"
402 arguments:@[ @"SystemUiOverlay.bottom" ]];
403 [plugin handleMethodCall:methodCallSet result:resultSet];
404 [self waitForExpectationsWithTimeout:1 handler:nil];
405 #if not APPLICATION_EXTENSION_API_ONLY
406 OCMVerify([mockApplication setStatusBarHidden:YES]);
407 #endif
408
409 // Update to shown.
410 XCTestExpectation* enableSystemUIOverlaysCalled2 =
411 [self expectationWithDescription:@"setEnabledSystemUIOverlays"];
412 FlutterResult resultSet2 = ^(id result) {
413 [enableSystemUIOverlaysCalled2 fulfill];
414 };
415 FlutterMethodCall* methodCallSet2 =
416 [FlutterMethodCall methodCallWithMethodName:@"SystemChrome.setEnabledSystemUIOverlays"
417 arguments:@[ @"SystemUiOverlay.top" ]];
418 [plugin handleMethodCall:methodCallSet2 result:resultSet2];
419 [self waitForExpectationsWithTimeout:1 handler:nil];
420 #if not APPLICATION_EXTENSION_API_ONLY
421 OCMVerify([mockApplication setStatusBarHidden:NO]);
422 #endif
423
424 [flutterViewController deregisterNotifications];
425 [mockApplication stopMocking];
426 [bundleMock stopMocking];
427 }
428
429 - (void)testStatusBarStyle {
430 id bundleMock = OCMPartialMock([NSBundle mainBundle]);
431 OCMStub([bundleMock objectForInfoDictionaryKey:@"UIViewControllerBasedStatusBarAppearance"])
432 .andReturn(@NO);
433 id mockApplication = OCMClassMock([UIApplication class]);
434 OCMStub([mockApplication sharedApplication]).andReturn(mockApplication);
435
436 FlutterEngine* engine = [[FlutterEngine alloc] initWithName:@"test" project:nil];
437 [engine runWithEntrypoint:nil];
438 FlutterViewController* flutterViewController =
439 [[FlutterViewController alloc] initWithEngine:engine nibName:nil bundle:nil];
440 XCTAssertFalse(flutterViewController.prefersStatusBarHidden);
441
442 FlutterPlatformPlugin* plugin = [engine platformPlugin];
443
444 XCTestExpectation* enableSystemUIModeCalled =
445 [self expectationWithDescription:@"setSystemUIOverlayStyle"];
446 FlutterResult resultSet = ^(id result) {
447 [enableSystemUIModeCalled fulfill];
448 };
449 FlutterMethodCall* methodCallSet =
450 [FlutterMethodCall methodCallWithMethodName:@"SystemChrome.setSystemUIOverlayStyle"
451 arguments:@{@"statusBarBrightness" : @"Brightness.dark"}];
452 [plugin handleMethodCall:methodCallSet result:resultSet];
453 [self waitForExpectationsWithTimeout:1 handler:nil];
454
455 #if not APPLICATION_EXTENSION_API_ONLY
456 OCMVerify([mockApplication setStatusBarStyle:UIStatusBarStyleLightContent]);
457 #endif
458
459 [flutterViewController deregisterNotifications];
460 [mockApplication stopMocking];
461 [bundleMock stopMocking];
462 }
463
464 @end
FlutterEngine
Definition: FlutterEngine.h:61
+[FlutterMethodCall methodCallWithMethodName:arguments:]
instancetype methodCallWithMethodName:arguments:(NSString *method,[arguments] id _Nullable arguments)
FlutterViewController
Definition: FlutterViewController.h:57
FlutterPlatformPluginTest
Definition: FlutterPlatformPluginTest.mm:17
-[FlutterEngine runWithEntrypoint:]
BOOL runWithEntrypoint:(nullable NSString *entrypoint)
FlutterEngine_Internal.h
-[FlutterPlatformPlugin handleMethodCall:result:]
void handleMethodCall:result:(FlutterMethodCall *call,[result] FlutterResult result)
Definition: FlutterPlatformPlugin.mm:106
FlutterMacros.h
FlutterMethodCall
Definition: FlutterCodecs.h:220
FlutterBinaryMessenger.h
FlutterResult
void(^ FlutterResult)(id _Nullable result)
Definition: FlutterChannels.h:194
FlutterPlatformPlugin.h
engine
id engine
Definition: FlutterTextInputPluginTest.mm:89
FlutterPlatformPlugin
Definition: FlutterPlatformPlugin.h:11
platform_view_ios.h
FLUTTER_ASSERT_ARC
Definition: FlutterChannelKeyResponder.mm:13
FlutterViewController.h