Platform and Version
- iOS
- Development environment: Xcode 16.0 beta 5 (16A5221g), macOS 14.6.1 (23G93)
- Run-time configuration: iOS 18.0 beta 5 (22A5326g)
Description of Problem
Starting with iOS 18 SDK, test bundles containing a +load
method that accesses UIScreen.mainScreen
result in deadlock during test bundle injection.
Also filed as FB14703057
I'm looking for clarity on whether this behavior is considered a bug in iOS or whether we will need to change the implementation of our app.
Steps to Reproduce
-
Create a new iOS app project using Objective-C and including unit tests
-
Add the following code snippet to any
.m
file in the test target:@interface Foo: NSObject @end @implementation Foo + (void)load { UIScreen * const mainScreen = UIScreen.mainScreen; NSLog(@"%@", mainScreen); } @end
-
Run the tests
Expected Behavior
As with iOS 17 & Xcode 15, the tests run to completion.
Actual Behavior
With iOS 18 & Xcode 16, deadlock during test bundle injection.
I suggest you change your implementation here, as you're relying on initialization details for UIKit objects and how they behave prior to main
being run, which as you unfortunately found out here, is subject to change.
Note also that you wouldn't be able to write the same code in Swift — +load
in a NSObject
defined in Swift won't get called, as noted by the documentation. While you're using this pattern for testing, in a normal launch sequence, a method like this which runs prior to main
causes launch time impacts. Often, alternate patterns are available for needs in +load
which move the work to after main
is called, enabling faster app launch times. Swift removing this paradigm was discussed many WWDCs ago in this context of focusing in on faster launch times. For you and your testing needs, that guidance may not be directly applicable in this scenario, but I hope these notes help you see why you'll need to look for a new approach to meet your test setup needs than this one.
— Ed Ford, DTS Engineer