Reputation: 29572
We'd like to find a way to write iOS-only Swift code blocks in code that supports multiple Apple platforms and runs without warnings on both Xcode 14 and 15.
It's complicated by the fact that #if os(iOS)
evaluates to true for visionOS
so the test #if os(iOS) && !os(visionOS)
is needed to build iOS-only code on Xcode 15. However, this generates a warning on Xcode 14 since visionOS
is not recognized.
#if os(iOS) && (swift(<5.9) || !os(visionOS))
also generates warnings on Xcode 14.
We've found that the following runs warning free on both:
#if swift(>=5.9)
#if os(iOS) && !os(visionOS)
code block
#endif
#else
#if os(iOS)
code block
#endif
#endif
But this is ugly since the code block needs to be duplicated. Is there a better way?
Upvotes: 2
Views: 1067
Reputation: 385840
TLDR: Add a version-specific package manifest that defines a build condition when building for visionOS.
Full details:
I haven't tested this, so I'm not 100% sure it will work. Also, Xcode 15.0 and Xcode 15.1 did not ship with a visionOS SDK but did ship with Swift 5.9, so that also might cause problems. Am I willing to download Xcode 14.3, Xcode 15.0, and Xcode 15.1 to test this solution? No, but I encourage you to do so. 😅 Anyway…
You say you're an SDK vendor, so I assume you're distributing a Swift Package Manager (SwiftPM) package.
SwiftPM supports “Version-specific Manifest Selection”. You can create two package manifests: one named Package.swift
and another named [email protected]
. A build system that supports Swift 5.9 or later uses the [email protected]
manifest, and a build system that doesn't support Swift 5.9 uses Package.swift
.
Xcode 15.0 supports Swift 5.9, and earlier Xcodes do not. So Xcode 14 will use Package.swift
, and Xcode 15 (and eventually Xcode 16, etc.) will use [email protected]
.
Create [email protected]
as a copy of Package.swift
. Update the swift-tools-version
line at the top of [email protected]
to version 5.9. Then (still in [email protected]
) add a swiftSetting
to your target as follows:
.target(
name: "PaulSDK",
swiftSettings: [
.define("supportsVisionOS", .when(platforms: [.visionOS])),
]
),
Then, in your code, check whether you're building for visionOS by checking the build condition:
#if supportsVisionOS
print("heyo it's visionOS")
#else
print("great sadness")
#endif
Upvotes: 0
Reputation: 15053
Under Xcode 14.3 and Xcode 15, the following will allow you to compile without any warnings:
#if swift(>=5.9) && os(visionOS)
// visionOS code, if any, under Xcode 15
#elseif os(iOS)
// iOS code under Xcode 14/15
#endif
Of course you can add other #elseif os(xxx)
as needed (for example, macOS).
Under Xcode 14.2 you will get a warning about the unknown visionOS
but the code will otherwise build correctly without any code duplication.
Upvotes: 0