# iPhone Duo: preparare un'app

Il pieghevole di Apple esce il 23/10/2026 (preordini dal 16/10) con iOS 27.1.
Queste note vengono dal lavoro su Faraway dell'08/10/2026 e dalle pagine di
Apple lette quel giorno. Valgono per tutte le app, native o no.

## Il dispositivo

- **Chiuso**: schermo esterno 466×678 punti (1398×2034 pixel), più largo e più
  basso di un iPhone normale.
- **Aperto**: schermo interno 951×669 punti in orizzontale (2853×2007 pixel),
  con la piega a metà. Ogni metà è grande più o meno quanto lo schermo esterno.
- **Colonna di sistema a destra**: orologio, fotocamera e Dynamic Island stanno
  in una colonna di 84 punti sul bordo destro, sia chiuso sia aperto. Il
  `safe-area-inset-right` vale 84 su tutta l'altezza.
- **Posture**: chiuso, aperto, a libro (mezzo piegato), appoggiato, a tenda.
  Apple non vuole un layout per ogni postura: compatto chiuso, largo aperto.

## Cosa chiede Apple

Fonti: [Get ready for iPhone Duo](https://developer.apple.com/iphone-duo/),
[Make sure your app is ready](https://developer.apple.com/iphone-duo/prepare/),
[HIG: Designing for iPhone Duo](https://developer.apple.com/design/human-interface-guidelines/designing-for-iphone-duo),
[Preparing your app for iPhone Duo](https://developer.apple.com/documentation/technologyoverviews/preparing-your-app-for-iphone-duo).

- **Con quale Xcode si compila decide quanto schermo prende l'app.** SDK iOS 26
  o prima: aperto, l'app sta al centro con spazio vuoto intorno; chiusa, sta a
  sinistra della colonna di sistema. SDK 27: quasi tutto lo schermo, ma non la
  colonna. SDK 27.1 (Xcode 27.1): tutto lo schermo, e le barre di sistema
  (navigazione, strumenti, schede) diventano verticali sul lato destro.
- **Aprire e chiudere lascia l'utente dov'era**: stessa schermata, stesso
  stato, stesse funzioni in ogni postura.
- Aperto si può mostrare un livello in più (esempio di Apple: Mail chiuso
  mostra l'elenco o il messaggio, aperto tutti e due affiancati).
- Niente pulsanti o testi sulla piega. Nelle griglie, numero pari di colonne.
- Cambiamenti piccoli fra le posture: i controlli non devono saltare in giro.
- Niente larghezze fisse, niente decisioni sul modello di telefono, sullo
  schermo principale (`UIScreen.main`) o sull'orientamento: contano lo spazio
  disponibile e le size class. Su Duo una size class larga non vuol dire iPad.
- Immagini e video a tutto schermo con riempimento: controllare che non
  taglino cose importanti nel formato largo.
- Fotocamera: aprendo e chiudendo l'app può cambiare schermo e la fotocamera
  in uso può trovarsi a guardare dall'altra parte.
- In Xcode 27.1 c'è una skill che controlla il progetto: chiedere
  all'assistente «get my app ready for iPhone Duo», oppure esportarla con
  `xcrun agent skills export` per usarla con un altro agente.

## App Store

- Screenshot del Duo: esterno 1398×2034 (o 2034×1398), interno 2007×2853 (o
  2853×2007). Facoltativi; obbligatori restano quelli dell'iPhone «medium».
  Apple consiglia di mostrare l'app in più orientamenti.
- In App Store Connect, nei dettagli per la promozione («Helpful Details»), si
  può segnalare che l'app è ottimizzata per iPhone Duo.
- Le build compilate con Xcode 27.1 RC App Store Connect le accetta (Faraway
  1.0.4, build 11 e 12, 08/10/2026: «Pronta per l'invio»).

## Provarlo sul Mac

- **Xcode 27.1 RC** in `/Applications/Xcode-27.1-RC.app`, accanto al 27.0. Si
  usa mettendo `DEVELOPER_DIR=/Applications/Xcode-27.1-RC.app/Contents/Developer`
  davanti ai comandi; `xcode-select` non si cambia, ci lavorano altre sessioni.
- Il runtime iOS 27.1 ha **solo** il Duo
  (`com.apple.CoreSimulator.SimDeviceType.iPhone-Duo`). Ogni app crea il suo
  simulatore con un nome suo («Faraway iPhone Duo»…).
- Simulator.app non c'è più: c'è **Device Hub**
  (`Xcode-27.1-RC.app/Contents/Applications/DeviceHub.app`).
- **Il simulatore si accende dal pulsante Start di Device Hub.** Acceso solo
  con `simctl boot` non viene disegnato: l'app sembra bloccata sulla splash.
- **Aprire e piegare** solo da Device Hub, con i pulsanti in fondo alla finestra
  del dispositivo (dopo quello di rotazione): chiuso, a libro, aperto. Da riga
  di comando non si può, e `simctl io screenshot` vede solo lo schermo esterno.
- **Senza mouse, quasi tutto.** Device Hub serve solo per accendere il Duo e
  aprirlo o piegarlo. Una volta acceso da Device Hub, `simctl io <id>
  screenshot` cattura lo schermo **in uso**: aperto, quello interno a
  2853×2007, giusto per App Store Connect. Per andare in una schermata precisa
  senza toccare: una build di prova legge da `localStorage` cosa mostrare, uno
  script lo scrive nel file del simulatore ad app chiusa e rilancia l'app
  (Faraway: `docs/store/schermate/duo/LEGGIMI.md`).
- L'uso del computer (mouse e tastiera veri) blocca il Mac a Paolo e lotta con
  le finestre che usa lui: usarlo il meno possibile, solo per piegare il Duo.

## Trappole trovate

- **`UIRequiresFullScreen` va tolto dall'Info.plist.** Con la chiave, aperto,
  l'app gira in un riquadro verticale rimpicciolito al centro. Senza, prende
  tutto lo schermo interno anche se l'app è solo verticale. Su un'app solo
  iPhone la chiave non serviva a niente.
- **La piega è a metà dello schermo intero**, non a metà dello spazio utile:
  con la colonna di 84 punti a destra, due colonne uguali mettevano la piega
  dentro quella di destra. Le colonne si misurano dalla piega.
- **App web (PWA, Capacitor)**: Safari e WKWebView non dicono né dove sia la
  piega né come è piegato il telefono (WebKit non ha le viewport segments).
  Lo schermo aperto si riconosce dalla forma: largo almeno 860, alto almeno
  540, più largo che alto. La colonna di sistema arriva come
  `env(safe-area-inset-right)`: va rispettata anche in pulsanti fissi, fogli,
  dialoghi e fotocamera.
- Le `fetch` dalla WebView verso `http://localhost` del Mac, con l'SDK 27.1,
  non arrivano. Per leggere lo stato della pagina nel simulatore: la pagina
  scrive in `localStorage`, dal Mac si legge il file
  `Library/WebKit/<bundle>/WebsiteData/Default/*/*/LocalStorage/localstorage.sqlite3`
  del container dell'app (valori in UTF-16).
- **React Native / Expo**: le misure da `useWindowDimensions` (cambiano
  aprendo e chiudendo), mai `Dimensions.get('screen')` letto una volta sola;
  le zone sicure da `react-native-safe-area-context`, compreso il lato destro.
- **Expo 57 non compila con Xcode 27.1** (ExpoModulesJSI: «cannot find type
  '__ObjC::expo' in scope»): Swift 6.4 scrive i nomi C++ con `::` e lo script
  `expo-modules-jsi/apple/scripts/build-xcframework.sh` non li toglieva più
  dall'interfaccia. Correzione di Expo non ancora pubblicata
  ([expo/expo#50569](https://github.com/expo/expo/pull/50569)): in Quanto Basta
  è una patch di patch-package (`patches/expo-modules-jsi+57.1.0.patch`, una
  riga di `sed`). Dopo averla messa, cancellare i `.build-hash` dentro
  `node_modules/expo-modules-jsi/apple/Products/ExpoModulesJSI.xcframework/*/`.
  Per fare la patch: `npx patch-package expo-modules-jsi --exclude
  '\.DerivedData|/Products/|\.generated|\.xcframework-slices|\.swiftpm|package\.json$'`,
  se no ci finiscono dentro centinaia di file compilati.
- **Con barre di sistema** (native-stack con intestazione, tab bar nativa) e
  SDK 27.1, iOS le mette in verticale nella colonna di destra **anche da
  chiuso**; il contenuto però non si sposta da solo: il margine destro
  (84) va lasciato a mano. Meglio la zona sicura **della pagina** che quella
  della finestra: con due pannelli anche la barra della colonna di sinistra
  si mette in verticale sul suo lato destro, accanto alla piega. In Quanto
  Basta: `SafeAreaView edges={['right']}` di react-native-safe-area-context
  come `screenLayout` delle pile. Le barre disegnate in JS invece restano
  dove sono (Quanto Basta, 08/10).
- `useSafeAreaInsets()` chiamato fuori da `SafeAreaProvider` (per esempio nel
  componente che lo disegna) fa chiudere l'app all'avvio, solo in Release.
- **idb** (`idb ui tap`) conosce solo lo schermo esterno: con il Duo aperto i
  tocchi non arrivano. Per girare fra le schermate da aperto servono un link
  (`simctl openurl`) o una build di prova, come per Faraway.

