Resolving Xcode 12.5 App Extension Compilation Errors with Swift @available and API Availability
This article explains why Xcode 12.5 reports compilation failures for iOS app extensions when APPLICATION_EXTENSION_API_ONLY is true, demonstrates how to restructure shared frameworks and use Swift’s @available and #available annotations (as well as Objective‑C NS_EXTENSION_UNAVAILABLE_IOS) to mark non‑extension‑compatible APIs, and provides practical code examples for a clean, minimal‑impact solution.
Starting with Xcode 12.5, Apple requires every Extension Target to set APPLICATION_EXTENSION_API_ONLY = YES ; otherwise the build fails with the error “Application extensions and any libraries they link to must be built with the APPLICATION_EXTENSION_API_ONLY build setting set to YES”. The failure occurs because shared code between the host app and the extension often uses APIs that are not allowed in extensions, such as UIApplication.shared.open and UIApplication.shared.keyWindow .
The article first illustrates a typical project layout: a Host App, a Share Extension, a common Library framework, and a NetworkService framework. All three targets are set to APPLICATION_EXTENSION_API_ONLY = YES , but the shared frameworks still contain non‑extension‑only APIs, causing compilation errors.
Two naïve solutions are discussed. The first is to split the Library (and similarly NetworkService ) into two separate frameworks—one that only uses extension‑compatible APIs ( LibraryExtension ) and one that contains the rest ( Library ). While this works, it introduces a lot of refactoring overhead and forces the host app to adjust many import statements.
The second solution leverages a conditional compilation flag ACTION_EXTENSION (as shown in the snippet below) to isolate the offending code, but this approach also has limitations.
#if !ACTION_EXTENSION
// code that uses non‑extension APIs
#else
// alternative code for extensions
#endifTo avoid heavy refactoring, the article recommends using Swift’s API availability annotations. By marking functions that call prohibited APIs with @available(iOSApplicationExtension, unavailable, message: "This method is NS_EXTENSION_UNAVAILABLE.") , the compiler can still build the project with APPLICATION_EXTENSION_API_ONLY = YES while clearly indicating which APIs are off‑limits.
Swift’s @available attribute can express platform availability, version introduction, deprecation, obsolescence, and unavailability. Examples include:
@available(iOS 13.0, macOS 10.15, *)
@available(tvOS, unavailable)
@available(watchOS, unavailable)
public struct SearchField: View { ... }The syntax @available(platform version, ... , *) allows multiple platform‑version pairs, with the asterisk covering all other platforms. The article also explains the #available condition used at runtime, e.g.:
guard #available(swift 5.0), #available(iOS 13.0) else { return }Applying these annotations to the problematic function gotoAppSystemSetting resolves the build error:
@available(iOSApplicationExtension, unavailable, message: "This method is NS_EXTENSION_UNAVAILABLE.")
@available(watchOSApplicationExtension, unavailable, message: "This method is NS_EXTENSION_UNAVAILABLE.")
@available(tvOSApplicationExtension, unavailable, message: "This method is NS_EXTENSION_UNAVAILABLE.")
static func gotoAppSystemSetting() {
if let url = URL(string: UIApplication.openSettingsURLString) {
if UIApplication.shared.canOpenURL(url) {
UIApplication.shared.open(url, options: [:], completionHandler: nil)
}
}
}Beyond individual functions, the article stresses the importance of propagating @available markings through the call chain: any function that invokes a prohibited API must also be annotated, and callers of that function must be annotated as well.
For Objective‑C code, the equivalent is the NS_EXTENSION_UNAVAILABLE_IOS("…") attribute, which can be applied to functions, methods, or entire headers. Examples from system frameworks illustrate its usage.
In conclusion, the recommended approach is to use Swift’s @available(iOSApplicationExtension, unavailable) (or the Objective‑C NS_EXTENSION_UNAVAILABLE_IOS ) to clearly demarcate extension‑incompatible APIs, optionally provide default protocol implementations, and ensure that all upstream functions in the call chain carry the same annotations, thereby allowing the project to compile cleanly under the new Xcode 12.5 requirements.
Sohu Tech Products
A knowledge-sharing platform for Sohu's technology products. As a leading Chinese internet brand with media, video, search, and gaming services and over 700 million users, Sohu continuously drives tech innovation and practice. We’ll share practical insights and tech news here.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.