cashapp / AccessibilitySnapshot

Easy regression testing for iOS accessibility
Apache License 2.0
541 stars 67 forks source link

Fix accessing trait collection outside main queue #90

Closed luispadron closed 2 years ago

luispadron commented 2 years ago

Summary

With iOS 15 devices I am getting a UI access outside of main thread crash:

Main Thread Checker: UI API called on a background thread: -[UIView AS_traitCollection]
PID: 70497, TID: 20879363, Thread name: (none), Queue name: com.apple.root.user-initiated-qos, QoS: 25
Backtrace:
4   FormPresenter-Unit-SnapshotTests    0x000000010d30f738 -[UIView(DynamicTypeSnapshotting) AS_traitCollection] + 52
5   UIKitCore                           0x0000000184a891ac +[UIKeyboardCache enabled] + 40
6   UIKitCore                           0x0000000184a894f4 -[UIKeyboardCache cachedImageForKey:fromLayout:] + 52
7   UIKitCore                           0x0000000184a4f900 __37-[UIKBKeyplaneView prepareForDisplay]_block_invoke + 224
8   libdispatch.dylib                   0x0000000180108db0 _dispatch_call_block_and_release + 24
9   libdispatch.dylib                   0x000000018010a5a4 _dispatch_client_callout + 16
10  libdispatch.dylib                   0x000000018011b4ac _dispatch_root_queue_drain + 736
11  libdispatch.dylib                   0x000000018011bd28 _dispatch_worker_thread2 + 160
12  libsystem_pthread.dylib             0x00000001c99ccb04 _pthread_wqthread + 224
13  libsystem_pthread.dylib             0x00000001c99cb904 start_wqthread + 8
2022-05-24 11:12:14.345711-0400 AppHost-FormPresenter-Unit-Tests[70497:20879363] [reports] Main Thread Checker: UI API called on a background thread: -[UIView AS_traitCollection]
PID: 70497, TID: 20879363, Thread name: (none), Queue name: com.apple.root.user-initiated-qos, QoS: 25
Backtrace:
4   FormPresenter-Unit-SnapshotTests    0x000000010d30f738 -[UIView(DynamicTypeSnapshotting) AS_traitCollection] + 52
5   UIKitCore                           0x0000000184a891ac +[UIKeyboardCache enabled] + 40
6   UIKitCore                           0x0000000184a894f4 -[UIKeyboardCache cachedImageForKey:fromLayout:] + 52
7   UIKitCore                           0x0000000184a4f900 __37-[UIKBKeyplaneView prepareForDisplay]_block_invoke + 224
8   libdispatch.dylib                   0x0000000180108db0 _dispatch_call_block_and_release + 24
9   libdispatch.dylib                   0x000000018010a5a4 _dispatch_client_callout + 16
10  libdispatch.dylib                   0x000000018011b4ac _dispatch_root_queue_drain + 736
11  libdispatch.dylib                   0x000000018011bd28 _dispatch_worker_thread2 + 160
12  libsystem_pthread.dylib             0x00000001c99ccb04 _pthread_wqthread + 224
13  libsystem_pthread.dylib             0x00000001c99cb904 start_wqthread + 8

This PR corrects this crash by ensuring we access AS_traitCollection via the main queue.

This is a workaround while we figure out why this is now crashing on iOS 15+ simulator devices. From our investigation we found that UIKit is calling traitCollection from a background queue and thus causing this to crash. Without swizzling this crash does not occur.

NickEntin commented 2 years ago

Two thoughts:

  1. Should we limit this behavior to iOS 15+, since it doesn't seem to affect older versions?
  2. Let's add a comment in the code explaining why we're changing threading behavior here.
luispadron commented 2 years ago

Two thoughts:

  1. Should we limit this behavior to iOS 15+, since it doesn't seem to affect older versions?
  2. Let's add a comment in the code explaining why we're changing threading behavior here.

@NickEntin

Good call on #1, added and availability check! For #2 I added a comment!