Fix -[FlutterView focusItemsInRect:] crash (#165454)

Fixes #163999

The backing semanticsObject of the semantics container (which the
container holds a weak ref to) is deallocated after hot restart so
`[rootAccessibilityElement accessibilityElementAtIndex:0]` is returning
`nil`.

## Pre-launch Checklist

- [ ] I read the [Contributor Guide] and followed the process outlined
there for submitting PRs.
- [ ] I read the [Tree Hygiene] wiki page, which explains my
responsibilities.
- [ ] I read and followed the [Flutter Style Guide], including [Features
we expect every widget to implement].
- [ ] I signed the [CLA].
- [ ] I listed at least one issue that this PR fixes in the description
above.
- [ ] I updated/added relevant documentation (doc comments with `///`).
- [ ] I added new tests to check the change I am making, or this PR is
[test-exempt].
- [ ] I followed the [breaking change policy] and added [Data Driven
Fixes] where supported.
- [ ] All existing and new tests are passing.

If you need help, consider asking for advice on the #hackers-new channel
on [Discord].

<!-- Links -->
[Contributor Guide]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#overview
[Tree Hygiene]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md
[test-exempt]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#tests
[Flutter Style Guide]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md
[Features we expect every widget to implement]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md#features-we-expect-every-widget-to-implement
[CLA]: https://cla.developers.google.com/
[flutter/tests]: https://github.com/flutter/tests
[breaking change policy]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#handling-breaking-changes
[Discord]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Chat.md
[Data Driven Fixes]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Data-driven-Fixes.md
This commit is contained in:
LongCatIsLooong
2025-03-26 13:19:23 -07:00
committed by GitHub
parent d5751be500
commit 5339d083fd
2 changed files with 38 additions and 1 deletions

View File

@@ -67,7 +67,6 @@ AccessibilityBridge::AccessibilityBridge(
AccessibilityBridge::~AccessibilityBridge() {
[accessibility_channel_ setMessageHandler:nil];
clearState();
view_controller_.viewIfLoaded.accessibilityElements = nil;
}
UIView<UITextInput>* AccessibilityBridge::textInputView() {
@@ -382,6 +381,7 @@ void AccessibilityBridge::clearState() {
[objects_ removeAllObjects];
previous_route_id_ = 0;
previous_routes_.clear();
view_controller_.viewIfLoaded.accessibilityElements = nil;
}
} // namespace flutter

View File

@@ -2364,4 +2364,41 @@ fml::RefPtr<fml::TaskRunner> CreateNewThread(const std::string& name) {
latch.Wait();
}
- (void)testResetsAccessibilityElementsOnHotRestart {
flutter::MockDelegate mock_delegate;
auto thread = std::make_unique<fml::Thread>("AccessibilityBridgeTest");
auto thread_task_runner = thread->GetTaskRunner();
flutter::TaskRunners runners(/*label=*/self.name.UTF8String,
/*platform=*/thread_task_runner,
/*raster=*/thread_task_runner,
/*ui=*/thread_task_runner,
/*io=*/thread_task_runner);
id mockFlutterView = OCMClassMock([FlutterView class]);
id mockFlutterViewController = OCMClassMock([FlutterViewController class]);
OCMStub([mockFlutterViewController viewIfLoaded]).andReturn(mockFlutterView);
fml::AutoResetWaitableEvent latch;
thread_task_runner->PostTask([&] {
auto platform_view = std::make_unique<flutter::PlatformViewIOS>(
/*delegate=*/mock_delegate,
/*rendering_api=*/mock_delegate.settings_.enable_impeller
? flutter::IOSRenderingAPI::kMetal
: flutter::IOSRenderingAPI::kSoftware,
/*platform_views_controller=*/nil,
/*task_runners=*/runners,
/*worker_task_runner=*/nil,
/*is_gpu_disabled_sync_switch=*/std::make_shared<fml::SyncSwitch>());
platform_view->SetOwnerViewController(mockFlutterViewController);
platform_view->SetSemanticsEnabled(true);
OCMExpect([mockFlutterView setAccessibilityElements:[OCMArg isNil]]);
platform_view->OnPreEngineRestart();
OCMVerifyAll(mockFlutterView);
latch.Signal();
});
latch.Wait();
}
@end