Introducing anyAppleOS

Apple recently unified its operating system versioning by adopting year-based version numbers for the major releases of macOS, iOS, watchOS, tvOS, and visionOS. The operating systems that shipped in fall of 2025 all have an aligned version number of 26.0. Starting with the Swift 6.4 compiler, we’re taking advantage of this cross-platform version number alignment by introducing a new availability “platform” called anyAppleOS. This change will allow you to avoid boilerplate code when using new APIs and building for multiple Apple platforms.

To illustrate the improvement, here’s an example of code that iterates through a string's Unicode scalars via its utf8Span property:

// Swift Standard Library
extension String {
  @available(macOS 26.0, iOS 26.0, watchOS 26.0, tvOS 26.0, visionOS 26.0, *)
  public var utf8Span: UTF8Span
}

// Example
func printScalarValues(_ string: borrowing String) {
  if #available(macOS 26.0, iOS 26.0, watchOS 26.0, tvOS 26.0, visionOS 26.0, *) {
    var iterator = string.utf8Span.makeUnicodeScalarIterator()
    while let scalar = iterator.next() {
      print(scalar.escaped(asASCII: true))
    }
  } else {
    // Fallback on earlier versions...
  }
}

printScalarValues("🎉") // Prints \u{0001F389}

Since this code deploys to older versions of all of Apple’s operating systems, an if #available check specifying five different operating system versions is needed to handle the case where String.utf8Span is not available at runtime. Using anyAppleOS we can simplify both the utf8Span declaration and the if #available check:

// Swift Standard Library
extension String {
  @available(anyAppleOS 26.0, *) // 🆕
  public var utf8Span: UTF8Span
}

// Example
func printScalarValues(_ string: borrowing String) {
  if #available(anyAppleOS 26.0, *) { // 🆕
    var iterator = string.utf8Span.makeUnicodeScalarIterator()
    while let scalar = iterator.next() {
      print(scalar.escaped(asASCII: true))
    }
  } else {
    // Fallback on earlier versions...
  }
}

Source compatibility

Availability specified using anyAppleOS is interchangeable with platform-specific availability. For example, when compiling Swift code for macOS, code guarded by macOS 26 availability can use declarations that are available in anyAppleOS 26 and vice-versa:

@available(macOS 26.0, *)
func availableInMacOS26()

@available(anyAppleOS 26.0, *)
func availableInAnyAppleOS26()

if #available(macOS 26.0, *) {
  availableInMacOS26()      // ✅
  availableInAnyAppleOS26() // ✅ when building for macOS
}

if #available(anyAppleOS 26.0, *) {
  availableInMacOS26()      // ✅
  availableInAnyAppleOS26() // ✅
 } 

This means that library authors can adopt anyAppleOS to simplify their API declarations without breaking source compatibility and API users can adopt anyAppleOS without waiting for updates to libraries.

Since the OS version alignment starts at version 26.0, it is invalid to specify an anyAppleOS version lower than 26.0:

if #available(anyAppleOS 25.0, *) { } // ❌ error: '25.0' is not a valid version number for any Apple OS

Combining anyAppleOS and platform-specific availability

For some Apple platforms, Swift infers availability when it isn’t explicitly specified. For example, by default macCatalyst and visionOS availability are inferred from iOS availability:

@available(iOS 18.0, *) // Inferred: macCatalyst 18.0, visionOS 2.0
func availableIniOS18()

This inference can be overridden by specifying explicit availability for those platforms instead:

@available(iOS 18.0, macCatalyst 18.1, visionOS 2.1, *)
func explicitAvailability()

As a general rule, when availability for multiple platforms is specified simultaneously, the compiler prefers the specification for the most specific platform that matches the compilation target.

Availability specified using anyAppleOS works the same way. The compiler infers platform-specific availability from anyAppleOS availability, but this inference can be overridden. For example, imagine an API that is introduced first on macOS 26, iOS 26, and visionOS 26 but is not initially available on either watchOS or tvOS:

@available(anyAppleOS 26.0, *)
@available(watchOS, unavailable)
@available(tvOS, unavailable)
public func newAPI()

If support for these APIs were added later in watchOS 26.4 and tvOS 26.4, the availability attributes could be updated like this:

@available(anyAppleOS 26.0, watchOS 26.4, tvOS 26.4, *)
public func newAPI()

Conditional compilation

anyAppleOS can be specified as an argument to #if os(...), simplifying conditional compilation in cross-platform code:

// Before
#if os(macOS) || os(iOS) || os(watchOS) || os(tvOS) || os(visionOS)
// ... code specific to macOS, iOS, watchOS, tvOS, or visionOS
#endif

// After
#if os(anyAppleOS)
// ... code specific to macOS, iOS, watchOS, tvOS, or visionOS
#endif

Interoperability

Clang will also support anyAppleOS availability, bringing the same availability simplification to C, Obj-C, and C++:

// Before
__attribute__((availability(macOS, introduced=26.0)))
__attribute__((availability(iOS, introduced=26.0)))
__attribute__((availability(watchOS, introduced=26.0)))
__attribute__((availability(tvOS, introduced=26.0)))
__attribute__((availability(visionOS, introduced=26.0)))
@interface NewIn26
// ...
@end

// After
__attribute__((availability(anyAppleOS, introduced=26.0)))
@interface NewIn26
// ...
@end

Clang availability attributes that specify anyAppleOS availability are imported into Swift as you would expect.

Trying it out

anyAppleOS support is available for you to try in the latest Swift.org toolchain snapshots built from main.

42 Likes

I couldn't find it mentioned, is it possible to also express deprecated and obsoleted versions using anyAppleOS?

@available(anyAppleOS, introduced: 26.0, deprecated: 26.2, obsoleted: 26.4)
func shortLivedAPI() {

}

I think the rules, including overrides, would behave the same way as for just introduced!

1 Like

Yes, your example would work as intended.

5 Likes

Does this share any implementation details with the AvailabilityMacro experimental feature? Because the last time I tried, that did not play well with deprecated or obsoleted.

It would be very nice being able to define one's own "any Apple OS" shorthands for pre-26.0 OS versions, too.

Even better if @available(anyAppleOS 25.0, *) could magically mean @available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *) somehow, etc!

1 Like

Does this share any implementation details with the AvailabilityMacro experimental feature?

No, anyAppleOS support doesn't depend on the implementation of the experimental AvailabilityMacro feature. anyAppleOS is modeled as a distinct platform in the Swift compiler and there is no implicit macro expansion to platform-specific availability attributes happening. There is existing infrastructure for hierarchical platform availability inference that anyAppleOS leverages. You can visualize the relationship between Apple platform availability domains as a tree like this:

                anyAppleOS
        ┌────────┬──┴──┬──────────────┐
        │        │     │              │
     watchOS   macOS  tvOS           iOS
        │        │     │       ┌──────┼───────────┐
     watchOS   macOS  tvOS     │      │           │
     AppExt   AppExt  AppExt  iOS  visionOS   macCatalyst
                             AppExt   │           │
                                   visionOS   macCatalyst
                                    AppExt      AppExt

Each downward edge represents a relationship in which availability can be inferred from the platform above. The change is that anyAppleOS has been inserted into the hierarchy above watchOS, macOS, tvOS, and iOS.

3 Likes

Thanks, this is a massively appreciated. If I had to quibble about something, I’d think Darwin would probably be cleaner than anyAppleOS, especially since we already use Darwin as the import for common low-level routines for Apple operating systems, but let’s get real; anything is better than @available(macOS x.y, macCatalyst x.y, iOS x.y, tvOS x.y, watchOS x.y, visionOS x.y, carOS x.y, brainOS x.y, skynetOS x.y, apocalOS x.y, whateverElseIsNextOS x.y, etcOS x.y, *).

2 Likes

Unfortunately that would draw connections to the Darwin kernel, which has its own distinct version numbering scheme that doesn't quite line up with the user-facing OS. For example, when I run uname -r on macOS Tahoe 26.3.1, the output is 25.3.0.

4 Likes

But that used to be true of macOS and iOS too. No reason Darwin couldn’t get a little bump to its version number to get it lined up too. :slight_smile:

Sure, but we have to review the anyAppleOS pitch in the current reality where the numbers don't match up, and the Swift evolution process doesn't have any control over how Darwin kernel version numbers are determined.

3 Likes

Will SPM also add this?

4 Likes

If we used Darwin as the version number this would allow referencing older versions of Apple's software for example Darwin 24 would be macOS 15, iOS 18, etc.

Do people really think "Darwin" means the same thing as "any [modern] Apple OS"? I doubt most developers know what it refers to. The Darwin module present on Apple's OSs doesn't really mean anything other than ExtendedPOSIXAPIs, and plenty of Apple-OS-only projects probably get by without mentioning it at all. Furthermore, Clang and GCC have long treated darwin as an alias for macos in extended target triples (usually with altered understandings of version numbers), and this convention has extended out to plenty of projects across the internet thanks to it showing up in the uname command on macOS (to pick just two big ones, Python and Node.js).

It may be kind of clunky, but I'd go for the relatively clear anyAppleOS* over what's basically a legacy name that nobody uses in casual speech to refer to e.g. tvOS.

* If Apple ever releases an OS that isn't based on their general existing SDK, this might get confusing. But if Apple releases an OS that does provide their general SDK shape, but, say, changes out the kernel, is that still "Darwin"?

14 Likes

Whaddayamean “any”?

5 Likes

Is anyAppleOS considered final, or is naming still open for discussion?

I’m a bit concerned about the "any" prefix here, since it already has a well-established meaning in Swift (existentials), which could be slightly confusing in this context.

Personally, I’d prefer:

@available(appleOS 26.0, *)

as it feels more consistent with the existing style of:

@available(macOS 26.0, iOS 26.0, watchOS 26.0, tvOS 26.0, visionOS 26.0, *)
5 Likes

Cool. We can finally replace the wrong #if canImport(Darwin) check everywhere since it can also indicate other Darwin kernel OS but is not appleOS.

2 Likes

No. But you can also use this to simplify future* AvailabilityMacro.

Eg.

AvailabilityMacro=FeatureA:macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0
...
AvailabilityMacro=FeatureB:macOS 26.0, iOS 26.0, watchOS 26.0, tvOS 26.0

For FeatureB you may want to update to use AvailabilityMacro=FeatureB:anyAppleOS 26.0 instead.

It bears clarifying that this decision was reserved to the project sponsor (Apple) as owner of the various trade names and final arbiter of the taxonomy of its platforms. This thread is an announcement, not a pitch—the feature was pitched already as os(Darwin).

5 Likes

If it's open for discussion I'd say just "appleOS" (unless "appleOS" is planned for something else).

Just to reiterate Xiaodi's point above, the name for this is entirely Apple's choice as a vendor since it is a reference to their trademarks and operating system families. Whenever new operating systems are brought up and support is added to Swift, we don't debate or bikeshed how we represent those in compiler conditions (note that this thread is explicitly not in the Evolution subforum).

Instead, we defer to those vendors, often by simply adopting the canonical name for that OS. To wit, when Apple launched visionOS, there was no pitch or discussion about how to spell os(visionOS). This is a more complicated case since it represents a family of operating systems, but the same philosophy applies here—as the vendor, it is their choice to make.

6 Likes

This announcement came on a certain date that made me immediately doubt its veracity...

1 Like