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
.mfile 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