App macOS nativa Swift/SwiftUI + WebKit per testare siti su più dispositivi contemporaneamente. Alternativa leggera e nativa a Sizzy.
- Multi view — dispositivi affiancati con scroll orizzontale
- Single view — dispositivo singolo scalato alla finestra
- Sync scroll — scrolling sincronizzato via JS injection in WKWebView
- Live reload — ricarica automatica ogni N secondi (1/2/3/5s)
- User Agent per dispositivo — Safari iOS, Safari iPadOS, Chrome Android
- Screenshot PNG — esporta screenshot per dispositivo in cartella scelta
- Dispositivi custom — aggiungi qualunque dimensione + UA
- 20 dispositivi predefiniti: iPhone SE → iPhone 16 Pro Max, iPad mini → iPad Pro 12.9", Samsung Galaxy, Pixel, OnePlus, Xiaomi
# Installa XcodeGen se non ce l'hai
brew install xcodegen
# Nella root del progetto
cd DevicePreviewer
xcodegen generate
# Apri in Xcode
open DevicePreviewer.xcodeprojPoi ⌘R per buildare e avviare.
-
File > New > Project > macOS > App
- Product Name:
DevicePreviewer - Interface:
SwiftUI/ Language:Swift - Deployment Target: macOS 13.0
- Product Name:
-
Elimina i file generati automaticamente:
ContentView.swiftDevicePreviewerApp.swift(quello generato da Xcode)
-
Trascina tutti i file
.swiftdella cartellaDevicePreviewer/nel progetto (assicurati che "Copy items if needed" sia selezionato) -
Aggiungi WebKit framework:
- Seleziona il target nel Project Navigator
- Tab General → Frameworks, Libraries, and Embedded Content
+→ cercaWebKit→ aggiungiWebKit.framework
-
Info.plist: sostituisci quello generato con il file
Info.plistincluso (serveNSAllowsArbitraryLoadsper caricare http:// localhost) -
Entitlements: nella tab Signing & Capabilities → App Sandbox:
- ✅ Outgoing Connections (Client)
- ✅ User Selected File → Read/Write
(oppure usa il file
.entitlementsincluso)
-
⌘R → Build & Run
DevicePreviewer/
├── DevicePreviewerApp.swift # @main entry point
├── AppState.swift # ObservableObject: URL, registry WKWebView, scroll sync, screenshot
├── DeviceModel.swift # Struct + catalogo 20 dispositivi
├── ContentView.swift # Layout principale + toolbar completa
├── DeviceListSidebarView.swift # Sidebar con checkbox dispositivi
├── MultiDeviceView.swift # Vista multi-dispositivo (HStack scrollabile)
├── SingleDeviceView.swift # Vista singolo dispositivo (auto-scale)
├── DeviceCardView.swift # Card: header + WKWebView scalato
├── WebViewRepresentable.swift # NSViewRepresentable per WKWebView + scroll JS
├── AddCustomDeviceView.swift # Sheet aggiunta dispositivo custom
├── Info.plist # NSAllowsArbitraryLoads
└── DevicePreviewer.entitlements # Sandbox + network + file write
- Sync scroll: JS iniettato via
WKUserScripttracciascrolleventi conrequestAnimationFramee invia le coordinate percentuali (0..1) viawebkit.messageHandlers. L'app propaga a tutti gli altri webview eseguendowindow.scrollTo()viaevaluateJavaScript. - Screenshot: usa
WKWebView.takeSnapshot(with:completionHandler:)→NSImage→ PNG - Scale:
.scaleEffect(scale, anchor: .topLeading)+.frame(w*scale, h*scale)— il WKWebView renderizza a risoluzione reale del dispositivo, l'intera card viene ridimensionata visivamente - Live reload:
TimerscheduledTimer che chiamawebView.reload()sull'intervallo scelto - NSAllowsArbitraryLoads: necessario per caricare
http://localhost:xxxxin sviluppo locale
Apri DeviceModel.swift e aggiungi un elemento negli array iphones, ipads o androids:
DeviceModel(
name: "Galaxy Z Fold 5 esterno",
width: 346, height: 745,
userAgent: "Mozilla/5.0 (Linux; Android 14; SM-F946B) ...",
category: .android
),