Last week, a post by React Native core developer Krzysztof Magiera sparked a lively discussion across the Apple developer community. In the post, he demonstrated an example where, with the main thread blocked, a back-and-forth animation in UIKit continued to run normally while the equivalent SwiftUI animation came to a halt. He attributed this to SwiftUI not using Core Animation’s render-server animation model and instead advancing animations within the app process, raising the question of whether SwiftUI is truly “native.” He later added that, in React Native, developers can still use Core Animation to create animations that continue running even when the main thread is blocked.
SwiftUI co-creator and early core developer Kyle Macomber responded with a different perspective. He explained that, from the beginning, SwiftUI deliberately moved away from server-side animation—where Core Animation advances animations on the render server—and instead chose to compute and advance animation values in the client/app process in exchange for better interruptibility and interactivity. This was not a technical regression, but a deliberate design trade-off. (SwiftUI did not abandon Core Animation itself; Core Animation still participates in the subsequent rendering process. What changed is who advances the animation.)
Ease of animation has always been one of SwiftUI’s signature strengths, and the continued evolution of its spring animations in recent years has further improved the naturalness of transitions and the expressiveness of interactive motion. For a reactive framework, I think advancing animations on the client side is entirely understandable. The trade-off, of course, is equally clear: as Krzysztof’s example demonstrates, when animation advancement depends on the app process, it becomes more susceptible to a busy main thread and also consumes more computational resources on the client side.
That said, client-side animation does not mean that all animation sampling calculations must happen on the main thread. As SwiftUI has evolved, some computationally intensive work involving animations and Shape can now be moved to background threads, reducing pressure on the main thread. Still, because animation advancement remains within the app process, and asynchronous computation is subject to constraints such as state updates and the rendering pipeline, animations can still stall when the main thread is completely blocked. Despite this “drawback,” starting with iOS 18, UIKit and AppKit also began adopting this client-side animation model: their new animation APIs can directly use SwiftUI’s Animation and are driven by the same underlying animation infrastructure rather than generating traditional CAAnimation objects.
This discussion presented an interesting situation: on the surface, the debate was about whether SwiftUI is truly “native,” but underneath it revealed a difference in framework design philosophies.
As Apple’s UI framework for the future, SwiftUI chose to depart from the established path, moving away from dependence on Core Animation’s render-server animation model in exchange for more flexible and expressive animation capabilities. In fact, John Harper, the creator of Core Animation, was himself one of SwiftUI’s co-creators. So this choice clearly wasn’t made out of unfamiliarity with Core Animation, but rather as an architectural decision made with an understanding of both its strengths and limitations. It also brought a less obvious advantage: some of SwiftUI’s core capabilities became further decoupled from the specific implementation details of Apple platforms. Although Apple has not open-sourced SwiftUI, architecturally, some of its core ideas are not inherently limited to Apple platforms.
From the React Native perspective, Krzysztof’s argument also has its rationale. As a cross-platform framework, one of React Native’s important goals is to make the best possible use of the capabilities each platform already provides, allowing apps to behave and perform more like “locals” on each platform.
What began as a discussion about “what counts as native” ultimately led core developers from both sides to explain how they think about UI animation architecture. As someone happily watching from the sidelines, I learned quite a bit from it as well.
Original
From pbxproj to xcproj: Xcode Project Configuration Gets a JSON Format
I’ve been waiting for Xcode 27.1, hoping to test how my apps adapt in the iPhone Duo simulator. Amusingly, 27.1 never arrived — Apple shipped 27.2 beta first instead. The iPhone Duo simulator is still missing, but the new project.xcproj caught my eye. What it replaces is project.pbxproj, the build graph inside the .xcodeproj bundle, not the bundle itself. What’s good about it, what does it fix, and what stays the same? This article takes a look.
Recent Recommendations
How we built Devin’s Mac
When an AI agent runs locally, permissions have long since been granted, the toolchain is ready, and a human can dismiss any dialog that appears. Move to the cloud and every one of those assumptions has to be rebuilt. The payoff isn’t doing something the local machine can’t — it’s turning the development environment itself into a resource you can assign to an agent: tasks run asynchronously, stay isolated from one another, pause and preserve their state when idle, resume on demand, and scale more easily to several agents working in parallel. Jon Kelley walks through building Devin’s macOS cloud environment, covering virtual machines on Virtualization.framework, disk snapshots, network isolation, pre-configured environments and permissions, live streaming of the desktop and Simulator, and computer use driven by the accessibility tree. That last point is especially instructive for Apple developers: good accessibility support also gives agents a structured interface for automated verification.
iOS 27: CrashReportExtension Framework
Traditional crash handling has an awkward problem: by the time the signal handler runs, the process it lives in may already be unreliable — memory may be corrupted, locks may still be held, and many everyday APIs can’t be called safely. The new CrashReportExtension in iOS 27 changes that execution model. After the app crashes, the system launches a separate extension and hands it a read-only CrashedProcess for inspecting the crashed process.
Anton Gubarenko demonstrates how to create and use the extension, along with several practical judgments. The API complements Apple’s .ips reports rather than replacing them, and suits teams that need their own backend, correlation with business context, or on-device pre-analysis. The extension itself should stay small, doing nothing more than generating and persisting a report; uploads and retries belong in the host app, with the two sharing storage through an App Group. For most indie developers, system crash reports plus MetricKit remain sufficient.
How SwiftUI animation works
For animation, developers only change state and specify an animation function, leaving the rest to SwiftUI. But how do those declarations become a continuous sequence of frames on screen? Starting from Transaction and AttributeGraph, and drawing on his work on OpenSwiftUI, Kyle Ye analyzes step by step how SwiftUI creates an animation context, computes intermediate states, and keeps updating views and layout as the animation runs.
Unlike the conventional approach of leaving interpolation mostly to the render server, many SwiftUI animations advance within the app process. Because interpolation happens inside the view graph, any value conforming to Animatable can be sampled, which lets layout, Shape, and much more participate in animation, while the render server mainly handles layer properties. The analysis of the CABasicAnimation on the asynchronous commit path is particularly worth reading: it carries only the current frame’s sampled value and is replaced on the next frame — the presence of a CA animation object on screen does not mean the animation’s clock has been handed to Core Animation. This adds useful detail to the debate over whether SwiftUI animation is “native,” discussed in this issue’s editorial.
SwiftUI: Some New APIs/ContainerViews Useful For Duo!
The many poses of iPhone Duo present new challenges for toolbars. To make full use of the wider screen while preserving vertical space for content, the system moves controls normally placed at the top and bottom to the side of the screen in certain poses. But text buttons, custom views, and other traditional toolbar content don’t always suit a vertical arrangement, and the toolbar and tab bar may have to compete for limited side space. iOS 27.1 addresses this with APIs including ToolbarItemAxisBehavior, ToolbarVerticalBehavior, ToolbarVerticalCompressionBehavior, and toolbarVerticalEdge, giving developers finer control over a toolbar’s orientation, placement, and compression strategy when space runs short. Itsuki demonstrates how these new APIs behave, with code and videos.
What these APIs have in common is that they let developers declare a preference rather than dictate a result. Faced with the range of poses Duo introduces, describing the relationships between pieces of content and your layout preferences — and letting SwiftUI decide the final presentation based on the actual environment — beats writing layouts for specific device states.
Sheets and fold avoidance on iPhone Duo
When iPhone Duo is partially folded, the crease down the middle forms a region poorly suited to interaction, and buttons or other controls that land there become awkward to operate. Using sheets as his example, Sarun Wongpatcharapakorn shows how a single interface adjusts its size, position, and toolbar across Duo’s closed, open, landscape, portrait, and partially folded poses. System components including sheets, alerts, and menus already avoid the fold without developer intervention. For developers, that means reaching for system components first also means inheriting this adaptive behavior across device poses for free.
Tools
Vapor 5 Beta Released
Ten years after Vapor was born and six and a half years after Vapor 4 shipped, the community finally has the first beta of Vapor 5. It amounts to a near-complete rewrite — two years of work and roughly 49,000 lines changed. The central change is saying goodbye to EventLoop and EventLoopFuture and moving fully to Swift Concurrency built on structured concurrency, with NIO now largely hidden from the public APIs.
Vapor 5 also integrates more deeply with Swift HTTP Types, Swift Configuration, and Swift Service Lifecycle, and adds the experimental VaporMacros for compile-time type checking of routes and authentication. It requires Swift 6.4 and remains in beta. For a fuller account of what changed, see Tim Condon’s What’s New in Vapor 5 Beta.
Hinge: Set the Duo Simulator’s Fold Angle from the Command Line
Xcode 27.1’s Device Hub can adjust the fold angle of the iPhone Duo Simulator (hold Option to reveal it), but neither simctl nor devicectl offers a corresponding command. Hinge, from Artem Novichkov, fills the gap: it sets fold angles from 0 to 180° on the command line, and supports opening, closing, half-folding, and sweeping continuously between angles. Hinge also ships an Agent Skill, letting a coding agent change Duo’s fold state itself while verifying an app.
Enriched Markdown: Cross-Platform Markdown Rendering and Editing Without a WebView
The usual way to handle Markdown on mobile is to wrap it in a WebView. Enriched Markdown, from Software Mansion, takes a more thorough route: it renders Markdown and supports rich-text editing through each platform’s native text capabilities, and can emit clean Markdown again once the content has been edited.
It offers a standalone SwiftUI SDK, rendering Markdown with TextKit 2 and md4c, and also covers React Native, Android, and the web. Rather than settling for “Markdown that displays,” Enriched Markdown emphasizes a native feel: text selects normally, links, images, and code blocks hook into system menus, and the library supports VoiceOver, TalkBack, Dynamic Type, and right-to-left writing.