
SwiftUI Previews render inside Xcode's canvas, so you need a graphical macOS session on the rented Mac — a terminal alone is not enough. Once a desktop is in front of you, the canvas behaves exactly as it does locally; the real work is clearing the "Preview update failed" errors that interrupt remote sessions. This guide picks the right Figment plan for preview work, gets a desktop up, and walks the five most common build failures. Apple's authoring reference is Previews in Xcode.
For UI iteration with Metal-backed views, animations, or arm64-only simulator runtimes, request a physical M-series Mac from $95/month — the exact chip, RAM and disk are confirmed in the quote, and physical plans are request-based until supply is confirmed. The $29/month virtual Intel macOS environment (2 vCPU, 8 GiB RAM, 80 GiB disk) does run macOS and a compatible Intel Xcode toolchain, including Xcode 26 or earlier, per Apple's note in Porting your macOS apps to Apple silicon. It can build, preview and sign targets that Intel Xcode supports; it is not a shell into another Mac. What it cannot do is accelerate Metal on a GPU, run arm64-only simulator runtimes, or run Xcode 27.
Start a plan at Figment Mac hosting. If you are unsure which tier fits your project, share your Xcode version, the simulator runtimes you preview against, and whether your canvas uses Metal or AR views, and the quote will come back with a matching configuration.
The canvas is part of Xcode's GUI. Under the hood Xcode manages a dedicated simulator device set (visible via xcrun simctl --set previews list) and talks to it through XPC, which needs a live window server. An SSH session has no window server, so xcodebuild can compile your SwiftUI code but there is no path for a rendered frame to reach a terminal. To see the canvas you need a desktop session.
On the $29 virtual Intel macOS VM the desktop is reached through the included browser console — inbound SSH is not provided. On a physical Mac delivered through a Figment quote, confirm the access method (typically macOS Screen Sharing / VNC on port 5900) when the machine is set up.
From macOS: In Finder press ⌘K, enter vnc://YOUR_MAC_IP, and authenticate. Quality defaults to Adaptive; raise it under View → Connection Options.
From Windows or Linux: Use RealVNC Viewer or TigerVNC pointed at port 5900. If your delivered Mac has SSH enabled on your account, tunnel VNC through it:
# Only if SSH is enabled on your delivered Mac:
ssh -N -L 5901:localhost:5900 user@YOUR_MAC_IP
# Connect VNC client to localhost:5901
For a responsive canvas, aim for a round-trip latency under roughly 80 ms. Above that, resizing views and dragging parameter sliders becomes visibly sluggish; work in a compact window and keep the canvas zoom at 100% or less.
Display resolution. Xcode's canvas needs horizontal space for both the editor and the preview pane. Apple does not publish a specific canvas minimum, so test your own project, but 1440 × 900 is a comfortable floor for keeping the canvas toggle and preview toolbar visible without collapsing panes.
If the canvas is not visible after opening a SwiftUI file:
⌥⌘⏎ to toggle the canvas on.Work through these in order. Each entry lists the symptom, the root cause, and the exact fix.
1. Build error in an unrelated file
Symptom: Canvas shows "Preview update failed" immediately; Diagnostics names a module that is not the current file.
Cause: Previews require a successful build of the entire module. A syntax error or type mismatch anywhere in the target blocks the preview build.
Fix: Run Product → Build (⌘B). Clear every error first; the canvas will not render until the target builds cleanly.
2. Corrupted DerivedData
Symptom: Previews worked, then suddenly fail after an Xcode update or a large git pull; the error log mentions a module interface version mismatch or missing .swiftmodule.
Cause: Stale intermediate build products that do not match the current toolchain or source state.
Fix:
# Close Xcode first.
rm -rf ~/Library/Developer/Xcode/DerivedData
# Optional, for stuck module caches:
rm -rf ~/Library/Caches/com.apple.dt.Xcode
Reopen Xcode. The first preview after clearing DerivedData takes longer than usual.
3. Stale preview simulators
Symptom: Canvas spinner runs indefinitely; Diagnostics shows a simulator boot timeout or "device not found"; restarting Xcode does not help.
Cause: The previews simulator device set is in a bad state — a booted preview simulator crashed and left stale lock files.
Fix:
xcrun simctl --set previews delete all
Run this in a terminal on the rented Mac (the browser-console desktop on the VM, or Terminal.app in the VNC session on a physical Mac). Xcode recreates the preview device set the next time a preview is requested.
4. Scheme or target mismatch
Symptom: "Cannot preview in this file" or "Preview is unavailable for the current run destination"; the canvas is greyed out instead of showing a spinner.
Cause: The active scheme's run destination is a device or simulator architecture that does not match the file being previewed, or the file belongs to a target not included in the active scheme.
Fix: In the Xcode toolbar, change the run destination to an available simulator for the target platform. If the file belongs to a framework target, add that target to the scheme under Product → Scheme → Edit Scheme → Build.
5. Preview macro in the wrong target
Symptom: The #Preview macro or PreviewProvider compiles, but the canvas shows "No preview provider found in this file".
Cause: The preview code is in a file assigned to a test target. Test targets are not compiled into the preview build.
Fix: In the File inspector (right sidebar → Target Membership), check the application or framework target, not the test target. If you need previews alongside tests, move the preview code into a preview-only file inside the main target.
A few adjustments that help on physical Macs reached over VNC and on the browser console into the $29 virtual Intel macOS VM:
#Preview macros (Xcode 15+) over PreviewProvider. The macro's surface is more compact and it is Apple's current recommendation; measure your own project before claiming an incremental-build speedup.#Preview block with mock data so the preview build only recompiles the changed file and its dependencies.If Diagnostics shows nothing useful, collect the preview subsystem log on the rented Mac:
# Run in the Mac's own terminal (browser desktop on the VM, Terminal.app in VNC).
# If the predicate returns nothing on your Xcode version, drop it and grep the
# full stream for "preview" or "PreviewAgent".
log show \
--predicate 'subsystem == "com.apple.dt.preview"' \
--last 5m \
--info \
| tail -50
Also check crash reports for the preview agent:
ls ~/Library/Logs/DiagnosticReports/ | grep -i preview
Repeated PreviewAgent crashes usually recover with the two-step reset: delete DerivedData, then xcrun simctl --set previews delete all, then rebuild.
#Preview block worth copyingMultiple #Preview blocks in one file each appear as a named tab in the canvas, which is useful when you cannot comfortably open several files side by side on a remote screen:
import SwiftUI
struct ProductCard: View {
let title: String
let price: Double
var body: some View {
VStack(alignment: .leading) {
Text(title).font(.headline)
Text(price, format: .currency(code: "USD"))
.foregroundStyle(.secondary)
}
.padding()
.background(.regularMaterial, in: RoundedRectangle(cornerRadius: 12))
}
}
#Preview("In-stock item") {
ProductCard(title: "Running Shoes", price: 129.99)
.padding()
}
#Preview("Long title") {
ProductCard(title: "Ultralight Carbon-Fiber Trail Running Shoes Pro Max",
price: 299.00)
.padding()
}
Request an M-series Mac for smooth SwiftUI preview rendering at Figment Mac hosting, or go straight to /mac-hosting/start to request a quote.
Related guides: iOS SDK upgrade on a remote Mac · Submit to TestFlight from a remote Mac · GitHub Actions self-hosted runner on Mac