'Xcode giving warning when using await UIApplication.shared.open(settingsURL) in Swift async function
I am calling await UIApplication.shared.open(settingsURL) inside a Swift Task but I am getting an Xcode runtime warning:
UIApplication.open(_:options:completionHandler:) must be used from the main thread only
Task {
guard let settingsURL = await URL(string: UIApplication.openSettingsURLString) else {
return
}
await UIApplication.shared.open(settingsURL) // <-- runtime warning when called
}
The SDK shows these methods:
@available(iOS 10.0, *)
open func open(_ url: URL, options: [UIApplication.OpenExternalURLOptionsKey : Any] = [:], completionHandler completion: ((Bool) -> Void)? = nil)
@available(iOS 10.0, *)
open func open(_ url: URL, options: [UIApplication.OpenExternalURLOptionsKey : Any] = [:]) async -> Bool
The error message implies that it thinks I'm using the first, non-async one (because of the mention of the completion handler), but I'm not. UIApplication is marked with MainActor so my understanding is everything called via an instance of UIApplication is run on the main thread automatically. This works just fine for other things I've called on UIApplication elsewhere such as isRegisteredForRemoteNotifications.
The app runs fine, no crashes or anything, just the warning from Xcode.
Is Xcode just confused here or am I actually doing something wrong?
Screenshot:
EDIT: for those confused about MainActor, this is a useful read: https://www.swiftbysundell.com/articles/the-main-actor-attribute/
I can just wrap UIApplication.shared.open(settingsURL) in await MainActor.run but I'm still confused why MainActor doesn't work here / why Xcode thinks the wrong method is being called.
Solution 1:[1]
The error indicates you may be using Task {...} somewhere in your code that is not on the main thread.
With the following test code, I could not replicate your issue, using macos 12.3 Beta, Xcode 13.3,
targets ios 15 and macCatalyst 12. Tested on real devices, not Preview. It may be different on older systems.
This is the code I used in my tests:
struct ContentView: View {
var body: some View {
Text("testing")
.onAppear {
Task {
guard let settingsURL = URL(string: "https://duckduckgo.com") else { return }
await UIApplication.shared.open(settingsURL) // <-- NO runtime warning when called
}
}
}
}
Does this code give you the same warning?
EDIT-1: this also works for me.
struct ContentView: View {
var body: some View {
Text("testing")
.onAppear {
DispatchQueue.global(qos: .background).async {
Task {
guard let settingsURL = URL(string: "https://duckduckgo.com") else { return }
await UIApplication.shared.open(settingsURL)
}
}
}
}
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 |

