DEV Community

Cover image for Xcode 27: Everything Developers Need to Know
ArshTechPro
ArshTechPro

Posted on

Xcode 27: Everything Developers Need to Know

Xcode 27 is in beta right now (beta 4 at the time of writing), and it is a big release. Apple's official release notes are lots of lines of radar numbers and one-line bug fixes, which is great as a reference and terrible as a read.

Can you even run it?

Before anything else, check these three lines:

  • Xcode 27 requires a Mac running macOS Tahoe 26.4 or later.
  • Xcode 27 only installs and runs on Apple silicon Macs. If you are still on an Intel Mac, this release is the end of the line for you.
  • On-device debugging supports iOS 17+, tvOS 17+, watchOS 10+, and visionOS. Older devices are no longer debuggable.

It ships with Swift 6.4 and the SDKs for iOS 27, iPadOS 27, tvOS 27, watchOS 27, macOS 27, and visionOS 27.


Part 1: The breaking changes (read this section)

I am putting these first because they are the parts that turn into a red build log on Monday morning. Everything else is upside.

Intel is being phased out of your build settings

If a target's minimum deployment target is macOS 27.0 or DriverKit 27.0, it will no longer build Universal by default. The ARCHS_STANDARD setting drops x86_64 once MACOSX_DEPLOYMENT_TARGET or DRIVERKIT_DEPLOYMENT_TARGET is 27.0 or higher.

If you still ship to Intel Macs, you have two options:

  1. Keep your minimum deployment target below macOS 27.0.
  2. Explicitly add x86_64 back to the ARCHS build setting.

The macOS 27 SDK can still back-deploy Universal apps down to macOS 12, so this is a default change, not a hard removal.

The old linker is gone

ld64 has been removed and the -ld_classic flag is no longer supported. If you have that flag lingering in OTHER_LDFLAGS from some 2023-era workaround, delete it now. This one is a hard failure, not a warning.

On Demand Resources is deprecated

NSBundleResourceRequest and the whole On Demand Resources system are deprecated. The replacement is Background Assets, which got a solid round of improvements this release (more on that below).

PreviewProvider is deprecated

PreviewProvider and its family of preview modifiers are now deprecated. If you still have the old struct-based previews hanging around, this is your nudge to move to the #Preview macro.

Before:

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}
Enter fullscreen mode Exit fullscreen mode

After:

#Preview {
    ContentView()
}
Enter fullscreen mode Exit fullscreen mode

A real Swift source break

This one is subtle. A computed property that has both an init accessor and an array or dictionary literal as its initial value will no longer compile if the getter is declared before the init accessor. This is a known source break from SE-0508.

Broken:

struct S {
    var _strings: [String]
    var strings: [String] = ["hello"] {
        get { _strings }
        @storageRestrictions(initializes: _strings)
        init { _strings = newValue }
    }
}
Enter fullscreen mode Exit fullscreen mode

The fix is to reorder: declare the init accessor first, then the getter. Annoying, but a one-line move.

Duplicate Clang module names now fail

The Swift dependency scanner was optimized to skip redundant header searches, and the tradeoff is that every Clang module reachable from a single dependency scan must have a unique module name. Previously the scanner tolerated duplicates; now it may error out.

The two situations that trigger this in the real world:

  • An SDK or project that vends the same Clang module name from more than one location on the header search path.
  • Vendored third-party sources shipping a module.modulemap that redeclares a module already in the SDK.

If you get a mysterious scanning error after upgrading, this is the first thing to check.

C++ changes worth knowing

If you have C++ in your app, a few things moved:

  • The minimum macOS deployment target for the C++ standard library is now 11.0.
  • multimap::find and multiset::find no longer guarantee returning an iterator to the first equal element. libc++ used to do this by accident, and the Standard never promised it. Use lower_bound or equal_range if you were relying on it.
  • lower_bound and upper_bound on std::map and std::set behave differently for comparators that are not a strict weak order. Defining _LIBCPP_ENABLE_LEGACY_TREE_LOWER_UPPER_BOUND gets the old behavior back, but that escape hatch is going away, likely next release.
  • bitset::operator[] now returns bool, which is actually what the Standard says it should do.
  • std::allocator is now trivially default-constructible.

The upside is significant: associative and unordered containers got up to 11x faster in some functions, several algorithms got up to 3x faster, and distance on non-random-access segmented iterators improved dramatically. A number of C++ papers landed too, including std::optional<T&>, zip, and std::views::indices(n).


Part 2: Agentic coding is now a first-class citizen

This is the headline feature, and it is a lot more than a chat box.

The assistant moved out of the sidebar

The coding assistant now lives in the editor area, not the navigator, with a redesigned conversation transcript. Artifacts the agent produces (code diffs, plans, SwiftUI preview snapshots) show up next to the transcript, and you can annotate code snippets and plan documents to give targeted inline feedback without leaving the conversation.

The sidebar is now dedicated purely to organizing conversations: real-time status, unread indicators, drag-and-drop grouping, archiving, renaming, multi-select for bulk actions, and a context menu to open conversations in new tabs, windows, or editor panes.

There is also a New Conversation button in the toolbar that works from anywhere in Xcode, with a status indicator you can click to jump to whichever conversation needs your attention.

Plan mode

Planning is now a proper feature rather than a prompting trick. Plans appear as editable Markdown artifacts next to the conversation. You review, annotate, discuss changes, and approve before the agent writes any code.

This is the workflow I would recommend for anything non-trivial: get the plan right first, then let it execute.

Agents can actually run your app

This is the part that changes what agents are useful for. In Xcode 27, agents can:

  • Boot simulators, install and launch apps, synthesize touch events, and capture screenshots to verify UI behavior.
  • Manipulate the active run state, read and interact with the debugger console.
  • List and switch between schemes and run destinations.
  • Inspect and modify build settings, compiler flags, entitlements, and Info.plist keys.
  • Access project insights such as crashes, disk writes, energy, hangs, and launch issues affecting your shipped app.

In other words, an agent can now write a fix, build it, run it, look at the screen, and check whether it worked.

Gemini, ACP, and plugins

  • Google Gemini is now available in the coding assistant alongside the existing options.
  • Xcode supports the Agent Client Protocol (ACP).
  • Agents can be extended with plugins containing skills, MCP servers, and ACP agent configurations. Skills are invokable as slash commands with completion support.
  • Apple ships its own specialists for targeted tasks like localization, UIKit resizing, and accessibility.
  • Two security-focused skills landed in beta 3: adopt-c-bounds-safety for a file-by-file -fbounds-safety adoption workflow, and audit-xcode-security-settings to suggest security-oriented build settings and entitlements.

Plugin authors can customize how their MCP servers appear in the UI using _meta fields:

{
  "name": "MyGreatPlugin",
  "description": "An awesome MCP server configuration.",
  "version": "1.0.0",
  "mcpServers": {
    "MyGreatMCP": {
      "type": "http",
      "url": "...",
      "tools": ["*"],
      "_meta": {
        "ideToolIconPath": "./icon.svg",
        "ideToolIconRendersAsTemplate": true,
        "ideToolTitles": {
          "whoami": "Who Am I",
          "get-current-email": "Get Current Email Message"
        }
      }
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

A sandbox for agents

Coding Intelligence includes a new security layer that monitors and controls filesystem access by coding agents and any processes they spawn. It is opt-in via Coding Intelligence settings. If you are nervous about letting an agent loose in your repo, turn this on before you do anything else.

One known issue to watch

If the "Implement the plan?" confirmation bar appears while the agent is still streaming, clicking Yes or No can start a new agent turn on top of the in-flight one and leave the conversation in a broken state. Wait for the agent to finish responding before confirming.


Part 3: Device Hub replaces the Simulator workflow

Device Hub is the new unified interface for both simulators and physical devices. Two features stand out.

Wireless pairing

You can now pair iPhone, iPad, and Apple Watch running OS 27 or later over a network. Click the + button in the Device Hub sidebar and choose "Pair Nearby Device". No cable needed for iPhone and iPad, and watch pairing is noticeably more reliable.

Mouse and trackpad gestures on iOS

Standard Mac gestures (scrolling, pinching, rotating) now work with UIKit components on iOS devices, physical or simulated.

There is a nuance worth understanding here. When you scroll with a pointing device, UIEvent.EventType.scroll is emitted. Pinch or rotate produces UIEvent.EventType.transform. But clicking with a mouse produces a simulated finger touch of type UITouch.TouchType.direct, not UITouch.TouchType.indirectPointer.

That is a convenience hybrid, not a faithful simulation. To validate real pointer behavior, use "Simulate Trackpad or Mouse" from the Device menu, test on a physical iPad with a paired pointing device, or use iPhone Mirroring.

Simulator boot is faster

Simulator runtimes now ship with a pre-built dyld cache, which makes the first launch of a simulator much faster. Small change, noticeable every single day.

Device Hub rough edges

Beta software, so expect some friction:

  • Game controllers only work with the visionOS simulator.
  • Video and input for a physical Apple Vision Pro are not supported (use AirPlay to view remotely). Everything else, like settings and DeviceFS, works.
  • Two-finger touches cannot be sent.
  • Scrolling over an Apple Watch face does not emulate the digital crown. Move the pointer over the crown in the bezel instead.
  • Devices may not appear during parallel testing even though tests are running. Disable parallel runs if you want to watch UI tests execute.
  • Downloaded app data containers land in a folder named after the bundle identifier rather than a proper .xcappdata bundle. The workaround is to rename the folder with an .xcappdata extension and nest the contents inside an AppData subfolder.

Part 4: Previews and Playgrounds

Previews got real quality-of-life work this cycle.

Argument grids

#Preview(arguments:) renders a grid of previews, one per argument. Click any cell to open it in Interactive mode. This is great for state matrices.

#Preview(arguments: [
    Order.empty,
    Order.singleItem,
    Order.manyItems
]) { order in
    OrderSummaryView(order: order)
}
Enter fullscreen mode Exit fullscreen mode

Resizable canvas

iOS previews get a Resizable Canvas mode so you can view your view in arbitrarily sized containers rather than fixed device frames. Helpful for adaptive layout work, and no longer constrained to specific size ratios.

Other improvements

  • Each #Preview and #Playground tab can be pinned independently in the canvas.
  • You can preview your UI in a different localization.
  • Code inside #Preview now explicitly runs on the main actor, so calling main-actor-isolated APIs no longer produces concurrency warnings or runtime check failures. That was a real annoyance under strict concurrency.
  • Holding Command routes zoom and scroll events to the canvas. Toggleable via Editor > Canvas.
  • Error messages across previews are meaningfully better: clearer timeouts, full diagnostics on MCP tool failures, and a placeholder view instead of a silent macOS fallback when a runtime is not installed.

Known issue: standalone Swift files opened by double-clicking in Finder may fail to run #Playground or #Preview blocks. Use File > Open, or drag onto the Dock icon.


Part 5: Localization becomes an agent workflow

This is probably the most immediately practical feature for small teams.

Agents can now translate strings in String Catalogs, from a single feature to an entire project, into one or more languages. Xcode handles the plumbing: it adds languages to your project settings, creates missing String Catalogs, and feeds context to the agent as it translates.

The String Catalog editor has a Generate Translations button, and you can right-click specific strings to translate just those.

Supporting changes that make this workable in a real pipeline:

  • A localization comment of "do not translate" automatically marks the string as Don't Translate in String Catalogs and translate="no" in exported XLIFFs.
  • Exported XLIFFs use state-qualifier="leveraged-mt" to flag machine-translated strings, so your human translators know what to review.
  • You can annotate translations in String Catalog artifacts when agents are translating.
  • Exporting localizations now extracts NSLocalizedString and similar macros from header files, not just implementation files. That is a fifteen-year-old bug report finally closed.
  • The "Prepare Project for Localization" tool surfaces newly added strings as artifacts, and shows keys removed because they no longer appear in source.

The honest take: this handles the bulk of the work, but you still want a professional translator reviewing the output before you ship to a new market.


Part 6: Instruments got a serious upgrade

If you do performance work, this might be the most valuable section of the release.

Swift Concurrency tooling

  • A new Swift Executors instrument shows tracks for the Cooperative Thread Pool, the Main Actor, and any type conforming to TaskExecutor or SerialExecutor. Full capture on OS 27; older systems show "Unknown executor".
  • Task tracks now group into Swift Task Collections, sorted by name or creation site. You can switch a collection track between showing task lifetimes and task states.
  • Tasks, Collections, Actors, and Executors have a Profile detail showing a call tree built from data captured while the task was running. Requires recording alongside Time Profiler or CPU Profiler.
  • Selecting a bar chart interval in an Actor or Executor queue plot lists the waiting tasks in the inspector.
  • Tasks and Actors whose lifetime started before the trace now show up, on a best-effort basis.
  • language swift task tree in LLDB prints a tree of every Swift Task the debugger knows about.

Foundation Models instrument

New instrument for tracing and debugging Foundation Models usage: instructions, prompts, responses, token usage, and inference performance. If you are shipping on-device AI features, you now have visibility into them.

System Trace and QoS

System Trace unifies system calls, VM faults, and thread states into a single plot, with a blending algorithm that keeps dense regions readable when zoomed out. You can walk the chain of scheduling events for a thread with left/right arrow keys, and the inspector offers quick actions like pinning the thread that made another thread runnable.

The System Trace template also graphs thread priority over time, which makes priority inversion and resource starvation much easier to spot. Thread Activity now displays effective QoS by default, with requested QoS available from the track dropdown.

Everything else in Instruments

  • Graphs no longer rescale to the local maximum when you pan the timeline, so comparisons across tracks are consistent. Manual rescale is under View > Rescale.
  • Pinned tracks are restored from the previous run, and can be saved and restored explicitly via View > Track States.
  • A new inspector shows details for the selected event with quick actions for pinning, filtering tracks, and filtering the detail view.
  • os_log data can be overlaid on process and thread tracks via the Track Graph Display popover.
  • os_signpost gets a track per signpost name, nested under the category.
  • The SwiftUI instrument records more detail about layout passes and why a layout computation was not cached, plus a "Summary of Updates" focus action on the view hierarchy.
  • Allocations marks tagged allocations with a (tagged) suffix when the process runs with Memory Integrity Enforcement.
  • Drag and drop .atrc, .logarchive, or .sample files onto the sidebar to create a run for each.
  • Memory usage when importing .atrc files dropped by roughly 1.5 GB on average.
  • Animation Hitches supports visionOS 27.0 and later.

On the command line, xctrace record accepts recording options as JSON (--show-recording-options prints the available ones), xctrace export can restrict a time range, and export now takes .atrc and .logarchive directly instead of requiring an import step first.

Deprecation: Instruments now requires iOS 17, watchOS 10, or tvOS 17 as a minimum on target devices.


Part 7: Organizer and production insights

The Organizer quietly became a planning tool rather than a crash dump viewer.

  • Insights Overview summarizes high-impact performance regressions across metrics and diagnostic reports, so you can prioritize instead of guessing.
  • The Hitches metric replaces Scrolling and covers all animations in your app, not just scroll.
  • Storage metrics track Documents & Data and app size across releases, which catches cache bloat and bundle growth.
  • AI-driven analysis generates recommendations for Crash, Energy, Disk Write, Hang, and Launch diagnostics, with links into your source and the coding assistant.
  • Metric goals now cover Battery Usage, Disk Writes, Hang Rate, Hitches, Memory, and Storage. Similar-app goals are supported for Hang Rate, on-screen Battery Usage, Disk Writes, and Storage, and Launch Time baselines were recalibrated.

Combined with agents having access to these insights, the loop is: Organizer flags a hang regression, you ask the agent about it, the agent reads the diagnostic and proposes a fix.


Part 8: Testing

  • XCUIVoiceOverService is a new UI testing API for verifying VoiceOver behavior. You can drive VoiceOver from UI tests and assert on focus, spoken output, and navigation. Accessibility testing that actually tests accessibility.
  • A launch test file template that opts into runsForEachTargetApplicationUIConfiguration, so the test runs across every combination of orientation, localization, and appearance your app supports.
  • Test plans let you choose how the system responds when the target app crashes during UI testing: off, warning, failure (the default), or fatal failure.
  • Mixing frameworks now warns you: calling an XCTest assertion inside a Swift Testing test (or the reverse) produces a warning-severity runtime issue. Configurable via the new interoperability setting in your test plan.
  • Filters were added to the test plan configurations tab, plus recent tests and open tests filters in the Test Navigator.
  • Large Swift Testing suites with many parameterized cases perform significantly better.
  • Test Repetition Mode now repeats individual Swift Testing cases instead of the whole test plan.

On the SwiftPM side, swift test summarizes failures at the end of a run, and supports --maximum-repetitions with --repeat-until [pass|fail] for hunting flaky tests. Only cases matching the condition get repeated.

swift test --maximum-repetitions 20 --repeat-until fail
Enter fullscreen mode Exit fullscreen mode

Part 9: Everything else worth a mention

Interface Builder builds without a simulator

A new IB compilation mode, toolchain, is enabled by default for UIKit documents. It compiles IB documents without downloading a simulator, which is a genuine win for CI and build servers.

Background Assets

Since On Demand Resources is deprecated, this matters:

  • Asset-pack manifests support path wildcards, file exclusion, hard-coded source roots, and custom destination subpaths.
  • Localized asset packs: the system delivers only the packs matching the user's preferred languages, cutting storage usage.
  • A Steam Asset Converter turns Steam depots into asset packs.
  • Xcode can serve asset packs to your app while debugging on device. Set a Background Asset Packs folder in the Run scheme action's Options tab.

StoreKit testing

  • New configuration UI for In-App Purchase offer codes, plus off-device purchase options to test them through the Transaction Manager.
  • Subscription Bundles and Subscription Suites can be configured for local testing.
  • Volume purchase transactions can be created for 1-month and 1-year auto-renewing subscriptions.

Swift and C++ interoperability

  • C++ constructors with default parameter expressions no longer require passing every argument explicitly from Swift.
  • Swift closures convert to std::function instances.
  • __counted_by and __noescape-annotated std::span parameters map to Swift Span without the experimental feature flag. Return values via __lifetimebound still need it.
  • Safe wrappers can be generated for functions taking std::span directly, without hiding the instantiation behind a typedef, as long as the parameter is __noescape.
  • The new SWIFT_REFCOUNTED_PTR macro bridges smart pointers to intrusively reference-counted types into Swift classes.

Debugging

  • LLDB can inspect data types with ~Copyable fields in the standard library and system frameworks.
  • LLDB ships with an MCP server (lldb-mcp).
  • In projects using bridging headers, LLDB imports explicitly built Swift modules and PCH from DerivedData directly. This can dramatically speed up the first po in a debug session, which has historically been painfully slow.

Documentation search

You can search developer documentation using natural language, with results matched semantically rather than by keyword.

Icon Composer 2.0

Supports a sharper rendering mode for the 2027 operating systems, with refractivity, outside specular, and deeper shadows. Edit the new properties in the group inspector and preview either design generation from the toolbar. One icon covers all OS versions.


Migration checklist

If you want the short version, here it is:

  1. Confirm you are on an Apple silicon Mac with macOS Tahoe 26.4+.
  2. Remove -ld_classic from your linker flags.
  3. Decide your Intel story: lower your deployment target, or add x86_64 to ARCHS explicitly.
  4. Migrate PreviewProvider to #Preview.
  5. Plan the move from On Demand Resources to Background Assets.
  6. Check for duplicate Clang module names if dependency scanning starts failing.
  7. Fix any init accessor ordering issues flagged by the Swift compiler.
  8. If you use C++, audit multimap/multiset find usage and any custom comparators.
  9. Turn on the agent filesystem security layer before letting agents run.
  10. Drop your minimum device targets for testing to iOS 17 or later.

Reference
Source: Xcode 27 Release Notes

Top comments (0)