Xcode 27 introduces enhanced test framework interoperability modes (Limited, Complete, Strict) that control how cross-framework issues are reported when mixing XCTest and Swift Testing in the same target, making it safer and more structured to incrementally migrate from XCTest to Swift Testing.
โข New interoperability modes (Limited, Complete, Strict, None) added in Xcode 27 โ previously there was no graduated control over cross-framework issue severity
โข Complete mode is now the default for new Xcode 27 projects, elevating cross-framework issues from warnings to errors
โข SPM gains equivalent mode support via swift-tools-version 6.4 and an environment variable override
โข `Test.cancel()` and `sourceLocation` parameter on `Issue.record` are now the canonical replacements for `XCTSkip` and `XCTFail(file:line:)` respectively
โข Three configurable interoperability modes (Limited, Complete, Strict) let teams control the severity of cross-framework issue reporting, enabling a gradual, low-risk migration path
โข Complete mode (default for new Xcode 27 projects) elevates cross-framework issues to errors, ensuring mixed-framework tests don't silently hide bugs
โข Strict mode causes a fatal error at the exact call site where XCTest API is used inside a Swift Testing test, making it trivial to pinpoint and replace legacy assertions
Shows a shared assertion helper being updated from XCTFail to Issue.record so it works correctly in both XCTest and Swift Testing tests under Xcode 27's Complete interoperability mode.
โ// SharedTestHelpers.swift โ old XCTest-only approachโimport XCTest+// SharedTestHelpers.swift โ works in both XCTest and Swift Testing targets+import Testingโ// Legacy helper using XCTFail with file/line for source attribution+// Updated helper: replaces XCTFail + file/line with Issue.record + sourceLocationfunc assertAllUnique<T: Hashable>(_ values: [T],โ file: StaticString = #file,โ line: UInt = #line+ sourceLocation: SourceLocation = #_sourceLocation) {var seen = Set<T>()for value in values {if seen.contains(value) {โ XCTFail("Duplicate value found: \(value)", file: file, line: line)+ Issue.record(+ "Duplicate value found: \(value)",+ sourceLocation: sourceLocation+ )}seen.insert(value)}}โ// --- XCTest using the shared helper ---โimport XCTest+// --- Swift Testing test using the shared helper ---+import Testingโclass FruitTests: XCTestCase {+struct Fruit: Hashable {+ let name: String+ let climate: String+}โ func testAllDeliveredFruitsHaveUniqueNames() {โ let names = ["Mango", "Apple", "Mango"] // intentional duplicateโ assertAllUnique(names)โ }+@Test("All delivered fruits have unique names")+func allDeliveredFruitsHaveUniqueNames() {+ let deliveryBatch: [Fruit] = [+ Fruit(name: "Mango", climate: "Tropical"),+ Fruit(name: "Apple", climate: "Temperate"),+ Fruit(name: "Mango", climate: "Tropical") // intentional duplicate+ ]+ // assertAllUnique now reports via Issue.record, so failures are+ // proper Swift Testing errors under Complete/Strict interop mode.+ assertAllUnique(deliveryBatch.map(\.name))+}โ func testFruitClimateIsTropical() throws {โ // continueAfterFailure = false halts on first failure globallyโ continueAfterFailure = falseโ let fruit = (name: "Lychee", climate: "Tropical")โ XCTAssertEqual(fruit.climate, "Tropical")โ }โโ func testSkipOnCI() throws {โ try XCTSkipIf(ProcessInfo.processInfo.environment["CI"] != nil,โ "Skipping on CI")โ // ... test bodyโ }+@Test("Fruit climate is tropical", .enabled(if: Locale.current.region?.identifier == "US"))+func fruitClimateIsTropical() throws {+ let fruit = Fruit(name: "Lychee", climate: "Tropical")+ // #require halts the test on failure โ replaces continueAfterFailure = false+ let climate = try #require(fruit.climate as String?)+ #expect(climate == "Tropical")}
iOS 27 adds sectioned queries, codable model attributes, ResultsObserver for non-SwiftUI change observation, and HistoryObserver for reacting to persistent history changes in SwiftData.
USDKit is a new first-party Swift framework introduced in iOS/macOS 27 that brings native USD scene creation, composition, modification, and export capabilities to Apple platform apps, with deep RealityKit and Spatial Preview integration.
LiveCommunicationKit is the modern replacement for CXProvider that delivers rich, native conversation UIs integrated with the Lock Screen, Dynamic Island, Phone app Recents, and Siri. It provides a unified lifecycle model for audio and video conversations with a single delegate-driven action pipeline.
In-depth guide
iOS 26 โ iOS 27 Migration Guide โโข Test plans created before Xcode 27 inherit Limited mode by default โ upgrade the mode manually in Test Plan Settings under Test Execution โข UI automation and performance testing remain XCTest-only; never migrate those โข Swift Testing tests cannot live inside XCTest classes โ keep them as free functions or in separate Swift Testing suites โข SPM projects must bump to swift-tools-version 6.4 to get Complete mode by default; override via SWIFT_TESTING_XCTEST_INTEROP_MODE environment variable
No hardware constraints; toolchain and test plan configuration only
The NowPlaying framework introduces a first-class Swift API for surfacing app media in system-wide now-playing surfaces โ Lock Screen, Control Center, Dynamic Island, StandBy, CarPlay, Apple Watch, and Apple TV โ via a declarative MediaSessionRepresentable protocol. It also supports remote media sessions (for controlling external speakers/TVs) and Media Sharing Extensions for routing media to third-party devices.