Przygotowanie aplikacji na iPhone Duo: przykład krok po kroku
Jak przygotować aplikację na iPhone Duo? Zbudować ją z SDK iOS 27.1, przeprowadzić przez każdą pozę w symulatorze, poprawić to, co wyjdzie po drodze, i zaplanować wysyłkę wokół dwóch dat, których Apple jeszcze nie ogłosił. iPhone Duo trafia do sprzedaży 23 października z iOS 27.1.1 O tym, co aplikacja na nim dostaje, decyduje wersja SDK zapisana w jej pliku binarnym: jeden i ten sam plik źródłowy zlinkowany jako 26.0, 27.0 i 27.1 pojawił się kolejno jako pudełko wielkości telefonu, jako okno obok listwy stanu i jako cały ekran z paskami z boku i zgłoszonym zgięciem.12 Na dzień 2 października znacznik 27.1 lub nowszy zapisują wyłącznie bety Apple (Xcode 27.1 beta, która ma symulator Duo, oraz Xcode 27.2 beta), a App Store Connect przyjmuje ich kompilacje do TestFlight, ale nie do sklepu.8 Ten wpis wykonuje całą pracę na Kiradex, aplikacji dla kolekcjonerów kart, którą mamy w TestFlight: co przyszło za darmo, co wychwyciło przejście przez pozy, a czego nie wychwyciła lektura kodu, zrzuty ekranu dla obu ekranów oraz brief, który można przekazać agentowi programistycznemu.
TL;DR
- Znacznik SDK jest przełącznikiem. iOS odczytuje wersję SDK z
LC_BUILD_VERSIONw pliku binarnym. Ze znacznikiem 27.1 sonda dostała cały ekran, 466 na 678 punktów po zamknięciu i 951 na 669 po otwarciu, z pionowymi paskami i zarezerwowanymi regionami. Ze znacznikiem 27.0 zatrzymała się 80 punktów przed krawędzią, przy której biegnie listwa stanu, zachowała poziome paski i nie dowiedziała się niczego o zgięciu. Ze znacznikiem 26.0 była telefonem 375 na 667 w pudełku. Własny znacznik można sprawdzić poleceniemotool -l.12 - Kalendarz ma dwie otwarte daty. TestFlight przyjmuje kompilacje z SDK 27.1 od 18 września, a kompilacje z bety 27.2 od 16 września; App Store przyjmuje tylko kompilacje z SDK 27.0; rozmiary zrzutów dla Duo są opublikowane, a ich przesyłanie „will be available later this year” (będzie dostępne jeszcze w tym roku).89 Przy przesyłaniu wymagany jest teraz także klucz ekranu startowego.10
- Większość zrobiły kontenery systemowe.
TabView,NavigationStackw czterech z pięciu kart i elementy paska narzędzi z tytułem i symbolem przeniosły paski Kiradex na bok bez żadnego kodu pisanego pod Duo. JedenArrangementViewpodzielił otwarty ekran i w pozie Book przesunął swój separator na zgięcie. JedenonHingeChangeodtwarza animację otwarcia aplikacji, gdy telefon się rozkłada.13 - Przejście przez pozy wychwyciło to, czego nie wychwyciła lektura. Arkusz, którego jedynym przyciskiem jest tekstowe „Done”, rezerwuje boczną listwę i zostawia ją pustą. Karta na pełnym ekranie wchodzi pod zewnętrzną kamerę. Po obróceniu do pionu podział układa się w stos. Karta otwarta w chwili rozkładania telefonu ląduje w układzie compact, rozciągniętym. Układ dla szerokości regular, napisany z myślą o ekranie wewnętrznym, psuje się na 6,9-calowym iPhonie w poziomie.13
- Dopóki sklep nie przyjmuje 27.1, jedno drzewo źródeł potrzebuje dwóch Xcode.
#availablenie pomaga; SDK 27.0 nie ma żadnegoArrangementView, z którym dałoby się skompilować kod. Nowe wywołania odgradza flaga kompilacji albo#if canImport(SwiftUI, _version: 8.0.85).14 - Zrzuty ekranu powstają w tym samym przebiegu. Zrzuty z symulatora mają dokładnie rozmiary wymagane przez App Store Connect, podobnie jak otwory w ramkach Duo udostępnionych przez Apple. Zasady Apple nadal wymagają ujęcia na wprost, bez modyfikacji i bez renderów 3D urządzenia.911
Stan rzeczy na 2 października
| Stan | Data | |
|---|---|---|
| Telefon | Przedsprzedaż 16 października, sprzedaż od 23 października, „available with iOS 27.1” (dostępny z iOS 27.1)1 | 9 września |
| SDK | Xcode 27.1 beta (27A9269) zawiera SDK iOS 27.1 i symulator iPhone Duo; kanał wydań Apple nie wymienia drugiej bety 27.1 ani wersji release candidate. Xcode 27.2 beta ma te same API i nie ma symulatora Duo814 | 18 września; kanał odczytany 2 października |
| TestFlight | Otwarty dla kompilacji z Xcode 27.1 beta i z bet Xcode 27.2, testy wewnętrzne i zewnętrzne8 | 16, 18 i 28 września |
| App Store | Otwarty dla kompilacji z Xcode 27 i SDK 27.0. Żaden wpis nie otwiera go dla SDK 27.18 | 14 września |
| Zrzuty dla Duo | Rozmiary opublikowane; przesyłanie „will be available later this year” (będzie dostępne jeszcze w tym roku)9 | 9 września |
| Ekran startowy | Wymagany przy przesyłaniu wszystkiego, co zbudowano z SDK iOS 27 lub nowszym10 | Nota techniczna zaktualizowana 14 września |
Trzy z tych wierszy czekają na Apple i żaden nie blokuje pracy. Kolejność, która wynika z tabeli: przenieść aplikację na SDK 27.1 i do symulatora, przeprowadzić ją przez każdą pozę, poprawić to, co wyjdzie, wrzucić tę kompilację do TestFlight, a wysyłkę do sklepu i zrzuty dla Duo trzymać w gotowości na dzień, w którym każda z tych rzeczy się otworzy.
Punktem wyjścia według samego Apple jest pierwsza z sześciu Tech Talks, dziesięciominutowa, i wszystko, co poniżej, zakłada jej znajomość:
Krok pierwszy: znacznik SDK decyduje, co daje telefon
Prezentacja zaczyna się od obietnicy zgodności w trzech poziomach. Aplikacja niezbudowana z SDK iOS 27 nadal działa: „When the device is closed, your app will use the screen space to the left of the status bar and camera. When the device is open, your app will be a familiar size and aspect ratio.” (0:36) (po zamknięciu urządzenia aplikacja zajmuje przestrzeń na lewo od paska stanu i kamery, po otwarciu ma znajomy rozmiar i proporcje). Aplikacja, która przyjęła SDK iOS 27, „will extend to the left of the status bar area on the inner display.” (0:58) (sięga na ekranie wewnętrznym aż na lewo od obszaru paska stanu). A dalej: „When you build your app with the iOS 27.1 SDK, your app extends to the edge of the screen. Standard navigation and toolbar buttons now lay out vertically under the status bar.” (1:05) (aplikacja zbudowana z SDK iOS 27.1 sięga do krawędzi ekranu, a standardowe przyciski nawigacji i paska narzędzi układają się pionowo pod paskiem stanu).3
Te poziomy nie są właściwością kodu. Są właściwością jednej liczby w pliku binarnym: wersji SDK, którą linker zapisuje w poleceniu ładowania LC_BUILD_VERSION, a iOS odczytuje przy starcie. Żeby zobaczyć, jak wiele od niej zależy, zbudowałem małą sondę, TabView z NavigationStack, który ma pięcioelementowy pasek narzędzi i ArrangementView, trzy razy z tego samego pliku źródłowego. Jedyna różnica między trzema plikami binarnymi to ta liczba: 26.0, 27.0, 27.1. Potem uruchomiłem wszystkie trzy w symulatorze iPhone Duo w każdej pozie.12

Jeden plik źródłowy, trzy znaczniki SDK, ekran otwarty i w pozycji pionowej. Od lewej: 26.0, 27.0, 27.1.
| Poza | Znacznik 26.0 | Znacznik 27.0 | Znacznik 27.1 |
|---|---|---|---|
| Zamknięty | 375 na 667, przeskalowane do przestrzeni obok listwy | 386 na 678, obok listwy | 466 na 678, cały ekran |
| Otwarty | 375 na 667, telefon na środku ekranu | 871 na 669 | 951 na 669 |
| Otwarty, obrócony | 375 na 667 | 669 na 871 | 669 na 951 |
| Zamknięty, obrócony | 667 na 375 | 678 na 386 | 678 na 466 |
| Klasa rozmiaru szerokości, otwarty | compact | regular | regular |
| Paski | wszędzie poziome | wszędzie poziome | pionowe, z wyjątkiem stanu otwartego i obróconego |
toolbarVerticalEdge |
nil | nil | trailing, z wyjątkiem stanu otwartego i obróconego, gdzie jest nil |
| Zarezerwowane regiony | brak | brak | zgięcie, obie kamery, kolumna stanu |
| Częściowo złożony | bez zmian | bez zmian | zgięcie staje się aktywnym podziałem; układy dzielone otwierają na nim przerwę |
Rozmiary okien podano w punktach, tak jak zgłosiło je okno każdej kompilacji.12
Środkową kolumnę warto przeczytać dwa razy, bo to ją większość aplikacji zaraz wypuści. Kompilacja z Xcode 27 dostaje szerokość regular na ekranie wewnętrznym i większą część ekranu, co jest realną poprawą wobec telefonu w pudełku z pierwszej kolumny. Zatrzymuje się 80 punktów przed krawędzią końcową, gdzie biegnie listwa stanu, nie dostaje pionowych pasków, a system nie mówi jej nic o zgięciu ani o kamerach: każde zapytanie o zarezerwowane regiony wracało puste, w każdej pozie, niezależnie od tego, ile razy sonda pytała.12 Żeby upewnić się, że znacznik jest uczciwym zastępstwem, skompilowałem też prostą wersję sondy samym Xcode 27.0, z jego własnym SDK iOS 27.0. Dostała te same okna: 386 na 678 po zamknięciu, 871 na 669 po otwarciu.12
Pisany przewodnik Apple jest tu mniej precyzyjny niż prezentacja, a jego sformułowania się zmieniły. 17 września jego wprowadzenie brzmiało „Build your app with Xcode 27.1 or later to use all of the available screen space on iPhone Duo. In earlier versions, your app doesn’t extend under the status bar and camera.” (aby wykorzystać całą przestrzeń ekranu, należy budować w Xcode 27.1 lub nowszym; we wcześniejszych wersjach aplikacja nie sięga pod pasek stanu i kamerę). Do 19 września zmieniło się na brzmienie aktualne także 2 października: „Build your app with the latest version of Xcode to use all of the available screen space on iPhone Duo. When you build with Xcode 26 and earlier, your app doesn’t extend under the status bar and camera.” (należy budować w najnowszej wersji Xcode; przy budowaniu w Xcode 26 i starszych aplikacja nie sięga pod pasek stanu i kamerę).2 Nowe zdanie wskazuje jako niewystarczające tylko Xcode 26 i starsze, a „latest version” nie mówi, czy beta się liczy, więc czytelnik mógłby uznać, że kompilacja z Xcode 27.0 dostaje cały ekran. W symulatorze tej bety nie dostaje. Dostaje środkowy poziom z prezentacji, a wcześniejsze sformułowanie zgadzało się z tym, co zmierzyłem. Dopóki sprzęt nie pokaże czegoś innego, warto planować według tabeli.
Zanim więc cokolwiek innego, należy sprawdzić znacznik testowanej kompilacji:
otool -l Build/Products/Debug-iphonesimulator/YourApp.app/YourApp | grep -A4 LC_BUILD_VERSION
Kompilacja debugowa z Xcode trzyma kod w YourApp.debug.dylib obok małego programu uruchamiającego, i oba pliki zawierają to polecenie. Szukamy sdk 27.1 lub nowszego; sonda ze znacznikiem 27.2, czyli tym, który zapisałby SDK z Xcode 27.2 beta, została potraktowana tak samo jak 27.1.12 W Kiradex odczyt to minos 27.0 i sdk 27.1: aplikacja instaluje się na iOS 27.0, a na Duo dostaje zachowanie 27.1.13
Naciskam na to, bo publicznie się pomyliłem. Mój pierwszy raport z tego symulatora, z 21 września, twierdził, że pasek narzędzi nigdy nie przechodził do pionu, a zarezerwowane regiony były puste w każdej pozie. Z betą było wszystko w porządku. Tamtą sondę skompilowałem, wywołując bezpośrednio swiftc -sdk, krok linkowania wziął jako katalog główny SDK macOS z tego samego Xcode, a plik binarny wyszedł ze znacznikiem 27.0: wszystko, co tamtego dnia zmierzyłem, było środkową kolumną. Tamten wpis zawiera teraz korektę.12 Jeśli układ dla Duo wygląda w symulatorze na wdrożony w połowie, z paskami u góry i martwym czarnym pasem z boku, należy sprawdzić znacznik, zanim zacznie się sprawdzać kod.
Aplikacja na warsztacie
Kiradex to aplikacja dla kolekcjonerów kart kolekcjonerskich, którą mamy w TestFlight: każdy zestaw, karty, które się ma, i te, których się szuka, ich wartość w czasie oraz każda karta jako obiekt 3D, który można obrócić. Jest darmowa, tylko na iPhone’a, działa na iOS 27.0 i nowszych i przechowuje listy kolekcjonera w jego własnym iCloud, bez żadnego naszego serwera po drodze.13 Nie jest skończona. Skaner nigdy nie zetknął się z prawdziwą kamerą, a do tego tygodnia nikt nie oglądał aplikacji na otwartym Duo: obok układu dla ekranu wewnętrznego jej roadmapa zawierała linijkę „Seen on the open Duo’s inner display only by the column maths; the simulator was folded shut.” (na wewnętrznym ekranie otwartego Duo oglądana tylko przez rachunek kolumn; symulator był złożony).13 To czyni ją uczciwym testem. Praca pod Duo, którą zawiera, została napisana na podstawie dokumentacji Apple i nigdy nie była sprawdzona na ekranie.
To, co robi dla Duo, jest niewielkie, i warto to wypisać właśnie dlatego, jak mało z tego to kod pod Duo:
- Nawigacja należy do systemu.
TabViewz pięcioma kartami, z których jedna ma rolę wyszukiwania, iNavigationStackw czterech z nich; skaner to widok kamery bez własnego paska. Elementy paska narzędzi toLabelz tytułem i symbolem, dołączone przez.toolbar. Nigdzie nie ma własnego paska. - Układ podąża za klasą rozmiaru. Szerokość compact dostaje trzykolumnową stronę segregatora i wypycha inspektor karty na stos. Szerokość regular, która w aplikacji tylko na iPhone’a oznacza w praktyce wewnętrzny ekran Duo, dostaje ścianę kart w parzystej liczbie kolumn; wybranie karty dzieli ekran między stronę a inspektor.
- Dwa wywołania z SDK 27.1. Podział to
ArrangementVieww stylu.split, zHStackjako rozwiązaniem zastępczym poniżej iOS 27.1. AonHingeChangeodtwarza animację otwarcia aplikacji, czerwone urządzenie, które się rozkłada, gdy telefon przechodzi ze stanu zamkniętego w jakikolwiek inny. - Bez blokady orientacji, za to z ekranem startowym.
Info.plistwymienia orientację pionową i obie poziome oraz deklarujeUILaunchScreen.13
To cała lista: dwa sprawdzenia dostępności w dwóch plikach. Wszystko inne, co telefon robi z tą aplikacją, robi z każdą aplikacją zbudowaną w ten sposób.
Ilustracje w tym wpisie pokazują aplikację w działaniu, z obrazami kart z publicznego katalogu, z którego korzysta. Kiradex jest niezależnym narzędziem dla kolekcjonerów, niepowiązanym z Nintendo, Creatures Inc., GAME FREAK inc. ani The Pokémon Company i przez nie niepopieranym, a obrazy kart należą do ich właścicieli.
Krok drugi: przejście przez każdą pozę
Przewodnik Apple ujmuje to przejście w cztery sprawdzenia:2
- „Confirm your views resize well in each supported orientation and pose.” (należy potwierdzić, że widoki dobrze zmieniają rozmiar w każdej obsługiwanej orientacji i pozie).
- „Inspect how the system presents your app’s navigation bars, toolbars, and tab bars vertically on the side of the display.” (należy przejrzeć, jak system przedstawia pionowo, z boku ekranu, paski nawigacji, paski narzędzi i paski kart aplikacji).
- „Identify any views, sheets, or popovers that position awkwardly when you fold or open iPhone Duo.” (należy wskazać widoki, arkusze lub popovery, które niezręcznie się ustawiają przy składaniu lub otwieraniu iPhone Duo).
- „Identify elements or controls in your views that appear in the fold, and are difficult to see or interact with.” (należy wskazać elementy lub kontrolki, które trafiają w zgięcie i są trudne do zobaczenia lub obsługi).
Wytyczne projektowe mówią, ile układów powinno to wymagać: „A compact width layout for the outer display and a regular width layout for the inner display give you the fundamentals for every pose.” (układ dla szerokości compact na ekranie zewnętrznym i układ dla szerokości regular na ekranie wewnętrznym dają podstawy dla każdej pozy).7
Pozy to przyciski w Device Hub: Closed, Book, Open i Rotate Right, a każda kombinacja to inny ekran. Przewodnik SwiftLee dodaje dokładniejszą kontrolkę, której nie potrzebowałem: „Holding Option ⌥ reveals a slider that you can use to control the hinge angle of the device with precision” (przytrzymanie klawisza Option ⌥ odsłania suwak do precyzyjnego ustawiania kąta zawiasu).17 Zanim spojrzy się na aplikację, warto wiedzieć, co system przekazuje każdej aplikacji w każdej pozie. Oto odczyty sondy ze znacznikiem 27.1:12
| Poza | Okno, punkty | Klasy rozmiaru (szerokość, wysokość) | Paski | Zgłoszone zarezerwowane regiony |
|---|---|---|---|---|
| Zamknięty | 466 na 678 | compact, regular | pionowe, krawędź końcowa | zewnętrzna kamera, 37 na 37, aktywna; kolumna stanu, 84 na 170, aktywna |
| Zamknięty, obrócony | 678 na 466 | compact, compact | pionowe, krawędź końcowa | zewnętrzna kamera, aktywna; obszar stanu, 84 na 82, aktywny |
| Otwarty | 951 na 669 | regular, regular | pionowe, krawędź końcowa | zgięcie, 40 szerokości od x 455 do 495, nieaktywne; wewnętrzna kamera, 58 na 37, nieaktywna; kolumna stanu, 84 na 120, aktywna |
| Book | 951 na 669 | regular, regular | pionowe, krawędź końcowa | te same trzy, ze zgięciem aktywnym |
| Otwarty, obrócony | 669 na 951 | regular, regular | poziome | zgięcie, 40 wysokości od y 455 do 495, nieaktywne; wewnętrzna kamera, nieaktywna; obszar stanu, 134 na 82, aktywny |
| Book, obrócony | 669 na 951 | regular, regular | poziome | te same trzy, ze zgięciem aktywnym |
Trzy rzeczy z tej tabeli ukształtowały wszystko, co nastąpiło potem.
Okno nie zmienia się, gdy telefon się składa. Book i Open zgłaszają ten sam rozmiar. Jedyna różnica, jaką aplikacja może zobaczyć, to przejście podziału zgięcia z nieaktywnego w aktywny oraz to, że zawias zgłasza częściowe otwarcie pod kątem 127 stopni tam, gdzie wcześniej zgłaszał pełne otwarcie pod kątem 180. Aplikacja, która odczytuje tylko swój rozmiar, nigdy się nie dowie, że telefon został złożony.
Zgięcie jest zawsze obecne i jest małe. Zgłaszane jest w stanie otwartym i złożonym, dokładnie pośrodku, a ramka zwracana przez API ma w obu stanach 40 punktów szerokości, z marginesem 20 punktów po każdej stronie. Prezentacja Apple mówi o regionie zgięcia: „When flat, it’s inactive and has a width of zero.” (7:32) (gdy urządzenie leży płasko, region jest nieaktywny i ma zerową szerokość). Symulator nie zwraca ramki o zerowej szerokości. Notatki terenowe Artema Novichkova opisują ten sam odczyt jako „40 pt wide, with 20 pt margins on each side of a zero-width fold line,” (40 pt szerokości, z marginesami po 20 pt z każdej strony linii zgięcia o zerowej szerokości)17 i ja również czytam zero z prezentacji w ten sposób, jako linię między marginesami; to moja interpretacja, a nie coś, co mówi tekst Apple. Prezentacja podaje też praktyczną wskazówkę: „By default, only active ones will be returned, but you can query for inactive ones” (domyślnie zwracane są tylko aktywne, ale można zapytać o nieaktywne) oraz „in grid-like layouts, you could prefer even numbers of columns when a division region is present regardless of its active state.” (w układach siatkowych warto preferować parzystą liczbę kolumn, gdy istnieje region podziału, niezależnie od jego stanu aktywności) (7:16, 7:41)5
Regiony przychodzą z opóźnieniem. Przy każdym uruchomieniu kilka pierwszych ewaluacji sondy nie odczytało żadnych regionów, a każda kolejna odczytywała pełny zestaw. Widok, który pyta raz, w pierwszym przebiegu układu, zapisuje w pamięci podręcznej pustą tablicę. Należy je odczytywać w body widoku, przy każdej ewaluacji; sonda przeliczała się co sekundę na timerze, a notatki Artema Novichkova ujmują regułę wprost: „Read them in the GeometryReader body so the view updates when they arrive. Don’t cache them.” (należy je odczytywać w body GeometryReadera, żeby widok zaktualizował się, gdy nadejdą; nie należy ich buforować).1217
Jedna uwaga praktyczna przed aplikacją. Runtime symulatora iOS 27.1 w tej becie obsługuje dokładnie jeden typ urządzenia, iPhone Duo; prośba o iPhone 18 Pro Max kończy się błędem „Incompatible device”. Dlatego porównanie poniżej, ta sama kompilacja na zwykłym iPhonie, działało na runtimie iOS 27.0, co jest też szybkim sposobem na potwierdzenie, że rozwiązania zastępcze za #available działają.12

Jedna kompilacja Kiradex na 6,9-calowym iPhonie, na zamkniętym Duo i na otwartym Duo. Nic w kodzie aplikacji nie przenosi pasków na bok.
Co wykazało przejście przez pozy
Test UI przeprowadził kompilację 5 przez osiem rodzajów ekranu w każdej z sześciu póz (siedem przy telefonie zamkniętym i obróconym, gdzie przycisk Ustawień przeniósł się do menu dodatkowych opcji), a skrypt w tym czasie robił zrzuty obu ekranów na każdym przystanku: 1398 na 2034 piksele na zewnątrz, 2853 na 2007 wewnątrz, czyli rozmiary wymienione przez App Store Connect.13 Zestawiona z czterema sprawdzeniami Apple, aplikacja zaliczyła więcej, niż się spodziewałem, i zawiodła w miejscach, których żadna lektura kodu nie wskazała.
Co przyszło za darmo
Paski. Po zamknięciu pasek narzędzi i wszystkie pięć kart stoją w listwie pod zegarem; po otwarciu tak samo; po otwarciu i obróceniu wracają na górę i na dół. Nic w aplikacji o to nie prosi. Druga prezentacja wyjaśnia, dlaczego paski budowane ręcznie zostają w tyle: „When used to build custom bars, content from sub-components like UIToolbar, UINavigationBar, or UITabBar won’t be considered.” (2:52) (jeśli posłużą do budowy własnych pasków, zawartość podkomponentów takich jak UIToolbar, UINavigationBar czy UITabBar nie zostanie uwzględniona).4 A ponieważ każdy element paska narzędzi na głównych ekranach to Label, każdy ma symbol dla listwy i tytuł dla menu dodatkowych opcji, co jest drugim warunkiem przewodnika: „If your item has a title and doesn’t have an icon, the system doesn’t present it vertically.” (jeśli element ma tytuł, a nie ma ikony, system nie przedstawia go pionowo).2
Zgięcie. Po otwarciu karty zestawu wiszą po sześć w rzędzie, czyli w liczbie parzystej, więc żadna karta nie wypada na środku ekranu. Po wybraniu jednej ekran dzieli się między stronę a inspektor karty w połowie obszaru treści aplikacji, na x 433. To 42 punkty na lewo od zgięcia, bo listwa zabiera 84 punkty z prawej strony, a dopóki telefon leży płasko, nie ma to znaczenia. W pozie Book widok układu przesuwa separator na zgięcie i zostawia 40-punktowy pas pusty: inspektor, który zaczynał się na x 433, teraz zaczyna się na 495. Aplikacja nie ma żadnego kodu dla pozy Book; to ArrangementView robi to, co opisuje prezentacja, „moving, resizing, or reorganizing what’s already there.” (6:04) (przesuwając, zmieniając rozmiar lub reorganizując to, co już jest na miejscu).513

Otwarty i płaski, a potem w pozie Book. Przerwa na drugim obrazie to zgięcie, i to nie aplikacja ją tam umieściła.
Arkusze, przy otwartym telefonie. Na ekranie wewnętrznym arkusz pojawia się wyśrodkowany, a jego przycisk Done pozostaje poziomy; w pozie Book arkusz sondy sam przesunął się na stronę początkową zgięcia.12
Zawias jako zdarzenie. Po rozłożeniu telefonu przy działającej aplikacji jej animacja otwarcia odtwarza się ponownie na ekranie wewnętrznym: czerwone urządzenie, zamknięte, a potem rozkładające się w aplikację. To jeden handler onHingeChange, który odpala, gdy stan przestaje być closed, i to dokładnie ten podział ról, o który prosi czwarta prezentacja: „Hinge data is observed live, and is ideal for driving interactions or effects. For layout, use the arrangement and region APIs.” (2:34) (dane zawiasu obserwuje się na żywo i świetnie nadają się do interakcji lub efektów; do układu należy używać API rozmieszczenia i regionów).6

Rozkładanie przy działającej aplikacji: animacja otwarcia to własne urządzenie aplikacji, narysowane przez aplikację i odtworzone przez zawias.
Co umknęło
Arkusz z jednym tekstowym przyciskiem rezerwuje listwę i zostawia ją pustą. Po zamknięciu arkusz Ustawień oddaje pas wzdłuż krawędzi końcowej na pionowy pasek, po czym nic w nim nie umieszcza: jedynym elementem paska narzędzi jest „Done” z tytułem i bez symbolu, a element czysto tekstowy pozostaje poziomy. Formularz zostaje ściśnięty w tym, co zostało. Sonda zmierzyła koszt: 374 punkty szerokości treści z zarezerwowaną listwą, 450 z wyłączonym pionowym paskiem.12 Prezentacja Apple wymienia ten przypadek: „if a sheet is control-heavy with only one item, like the close button here, consider disabling a vertical bar so it doesn’t reduce available space.” (14:37) (jeśli arkusz jest pełen kontrolek i ma tylko jeden element, jak tutaj przycisk zamknięcia, warto rozważyć wyłączenie pionowego paska, żeby nie zmniejszał dostępnej przestrzeni).4 Są dwie naprawy i sonda wypróbowała obie. Wystarczy dać przyciskowi symbol, Button("Done", systemImage: "checkmark"), a przenosi się do listwy jako wyróżniony znak zaznaczenia; albo dodać .toolbarVerticalBehavior(.disabled) do zawartości arkusza, a listwa znika, kosztem niższego arkusza.

Od lewej: arkusz aplikacji, a potem sonda z czysto tekstowym Done, z symbolem i z wyłączonym pionowym paskiem.
Karta na pełnym ekranie wchodzi pod kamerę. Popisowym elementem aplikacji jest karta na czarnej scenie z ukrytymi paskami, a ta scena ignoruje obszar bezpieczny na każdej krawędzi. Na ekranie zewnętrznym wysyła to górny róg karty pod kamerę. System zgłasza tę kamerę każdemu widokowi, który zapyta, jako aktywne przesłonięcie o boku 37 punktów, a jej położenie zgadza się z wycięciem we własnej grafice ramki Apple z dokładnością do półtora punktu.1112 Wytyczne projektowe Apple dopuszczają potraktowanie na pełną szerokość „as long as nothing conflicts with the Dynamic Island or the status bar.” (o ile nic nie koliduje z Dynamic Island ani z paskiem stanu).7 Naprawa polega na zachowaniu pełnego spadu dla czarnego tła i przesunięciu samej karty do środka: albo scena respektuje na tym ekranie obszar bezpieczny od góry i od krawędzi końcowej, albo odczytuje reservedRegions(kind: .occlusion) i kadruje kartę z dala od tego, co zwróci.

Zrzut przeglądarki w ramce Apple dla ekranu zewnętrznego. Zrzut z symulatora nie ma w sobie dziury; telefon ją ma.
Po obróceniu dwa panele układają się w stos. Otwarty i obrócony do pionu ekran ma 669 punktów szerokości i nadal szerokość regular, więc aplikacja nadal się dzieli. Ale widok układu, który wypełnia przestrzeń wyższą niż szerszą, dzieli się na górę i dół, zgodnie z przewodnikiem Apple: „it places the primary view on top and the secondary view below it when the containing view is taller than it is wide.” (umieszcza widok podstawowy na górze, a drugorzędny pod nim, gdy kontener jest wyższy niż szerszy).2 Wynikiem jest pasek, który pokazuje jeden rząd kart i początek drugiego, nad inspektorem. Własny komentarz aplikacji w tej linii mówi, że ta para „is only useful side by side,” (ma sens tylko obok siebie) i nic tego nie egzekwowało. Ograniczenie stylu przez .split.axes(.horizontal) to udokumentowana kontrolka,16 z haczykiem, który prezentacja wykłada wprost: „If the split arrangement cannot split among an axis, and it’s the primary axis, the arrangement view chooses to only show a single view.” (12:44) (jeśli układ dzielony nie może podzielić się wzdłuż osi, a jest to oś główna, widok układu pokazuje tylko jeden widok).5 Sonda potwierdza obie połowy: po wypełnieniu obróconego ekranu zwykły podział ułożył się w stos, a podział wyłącznie poziomy pokazał panel podstawowy i nic więcej.12 W tej aplikacji ukryłoby to inspektor, więc uczciwą naprawą jest decyzja, a nie modyfikator: gdy przestrzeń jest wyższa niż szersza, należy wypychać inspektor tak, jak robi to układ compact.

Po obróceniu: poziome paski, jak mówią wytyczne Apple, i podział, który poszedł w złą stronę dla tej pary widoków.
Karta otwarta w chwili rozkładania nie trafia do żadnego z układów. Po zamknięciu wybranie karty wypycha jej inspektor na stos nawigacji. Po rozłożeniu z widocznym inspektorem karta nadal tam jest, a to akurat łatwo zrobić źle. Ale to wciąż wypchnięty ekran, teraz o szerokości 951 punktów: scena po lewej, szczegóły w białym prostokącie dryfującym na czerni, przycisk Back w listwie. Projekt aplikacji dla tego ekranu to ściana z kartą obok, a jedyny sposób, żeby do niego dotrzeć, to wrócić i wybrać kartę ponownie. Jeden wybór steruje oboma układami; jedna ścieżka nawigacji już nie. Naprawa polega na wykryciu zmiany z szerokości compact na regular przy wybranej karcie i zdjęciu wypchniętego ekranu ze stosu, tak żeby przejął podział.

Ta sama karta przed rozłożeniem i po nim. Stan przetrwał; układ to compact, rozciągnięty.
Szerokość regular to nie „Duo”. Aplikacja traktuje szerokość regular jak ekran wewnętrzny: ściana, parzyste kolumny, podział. 6,9-calowy iPhone położony na boku też ma szerokość regular, przy wysokości compact, a aplikacja nie blokuje orientacji. Tam ta sama gałąź daje stronę odsuniętą od lewej krawędzi, inspektor z kolumną szczegółów zbyt wąską na nazwę karty i przyciski akcji ucięte przy dolnej krawędzi ekranu. Nic z tego nie jest nowe w iOS 27 i nie pojawiło się w żadnej pozie Duo, którą uruchomiłem; praca pod Duo to wykryła, bo po raz pierwszy ktoś przeszedł układ dla szerokości regular na każdym ekranie, który ją zgłasza. Sprawdzeniem, które rozdziela te dwa przypadki, jest druga klasa rozmiaru: ekran wewnętrzny ma regular w obu, a prezentacja Apple podaje ekran zewnętrzny obrócony na bok jako compact w obu.3 Układ, który potrzebuje miejsca w dwóch kierunkach, powinien pytać o oba.

Układ dla szerokości regular na telefonie, który nie jest Duo: 6,9-calowy iPhone na boku, iOS 27.0.
Klawiatura zasłania listwę. Przy wysuniętej klawiaturze na ekranie zewnętrznym karty z dolnej części listwy chowają się za nią. To układ systemu, a nie usterka; prezentacja mówi, że pasek może wymagać przepełnienia „as other competing UI appears, like the keyboard” (gdy pojawia się inny konkurujący interfejs, na przykład klawiatura) (11:50).4 Znalazło się to na tej liście, bo zepsuło narzędzia: mój pierwszy przebieg stuknął w „Collection” przy wysuniętej klawiaturze wyszukiwania, a stuknięcie trafiło w literę P. Testy UI, które zakładają, że pasek kart jest zawsze osiągalny, zawodzą właśnie tutaj.
Dwie mniejsze rzeczy. Aplikacja wybiera parzyste kolumny na podstawie klasy rozmiaru szerokości, podczas gdy prezentacja sugeruje kierować się samym regionem zgięcia, obecnym lub nie. I jedna, która nie ma nic wspólnego ze składaniem: otwarta cztery razy z rzędu na 6,9-calowym symulatorze pełnoekranowa przeglądarka pokazała kartę za pierwszym razem, a przez kolejne trzy pusty czarny ekran. Żadna z nich nie blokuje kompilacji w TestFlight. Obie były niewidoczne, dopóki aplikacja nie znalazła się na ekranie, a coś nie zaczęło po kolei naciskać jej przycisków.
Czego symulator nie mógł pokazać
Skanera. Otwiera tylny aparat szerokokątny i już korzysta z koordynatora obrotu, czyli z tego, o co prosi prezentacja o kamerze: „On iPhone Duo, the rotation coordinator will update when your app moves displays.” (8:19) (na iPhone Duo koordynator obrotu aktualizuje się, gdy aplikacja przechodzi między ekranami).6 Czy sesja przetrwa przejście z jednego ekranu na drugi, to pytanie do sprzętu; symulator nie ma żadnej kamery. Noty wydania Apple dodają StandBy i większość rozszerzeń aplikacji do tego, czego ten runtime nie potrafi uruchomić, a noty Xcode 27.2 beta 2 dodają jedną rzecz dla każdego, kto automatyzuje zrzuty: „Screenshots and recordings in iPhone Duo may be black for up to a few minutes after booting the device.” (zrzuty i nagrania z iPhone Duo mogą przez kilka minut po uruchomieniu urządzenia być czarne).20
Jedno drzewo źródeł, dwa Xcode
Kalendarz tworzy problem. Kompilacja, którą przyjmuje sklep, pochodzi z Xcode 27 i SDK 27.0; kompilacja, która zachowuje się poprawnie na iPhone Duo, pochodzi z SDK 27.1. Dopóki Apple nie otworzy sklepu dla tej drugiej, aplikacja, która chce wypuścić aktualizację i dalej pracować nad układem dla Duo, musi kompilować się w obu.
if #available(iOS 27.1, *) tego nie załatwia. Dostępność to pytanie czasu wykonania; kompilator i tak musi znaleźć symbol. Kiradex opakowuje swoje dwa wywołania pod Duo właśnie w ten sposób, a jej docelowa wersja wdrożenia to 27.0, więc kompilacja instaluje się na telefonie, który nie został zaktualizowany. Z SDK 27.1 to się kompiluje. W Xcode 27.0 plik, który robi to samo, zatrzymuje się na error: cannot find 'ArrangementView' in scope, bo SDK 27.0 nie ma takiego typu.14 Kiradex nie jest jeszcze w sklepie, więc może po prostu zostać przy narzędziach w wersji beta; aplikacja z klientami nie może.
Udokumentowane warunki Swifta też nie rozróżniają obu SDK. #if compiler(>=6.4) jest prawdziwe w obu: Xcode 27.0, Xcode 27.1 beta i Xcode 27.2 beta wypisują ten sam ciąg Apple Swift version 6.4 (swiftlang-6.4.0.34.1 clang-2100.3.34.1).14 Zostają dwie zapory, i sprawdziłem obie.
Warunek kompilacji ustawiony samodzielnie. To udokumentowana droga. Flagę należy zdefiniować tylko w konfiguracji budowanej z betą (w Xcode SWIFT_ACTIVE_COMPILATION_CONDITIONS = DUO_SDK, w wierszu poleceń -D DUO_SDK) i odgrodzić nią kod wymagający 27.1:
struct Pair<Primary: View, Secondary: View>: View {
@ViewBuilder var primary: Primary
@ViewBuilder var secondary: Secondary
var body: some View {
#if DUO_SDK
if #available(iOS 27.1, *) {
ArrangementView { primary } secondary: { secondary }
.arrangementViewStyle(.split)
} else {
HStack(spacing: 0) { primary; secondary }
}
#else
HStack(spacing: 0) { primary; secondary }
#endif
}
}
Bez flagi ten plik przechodzi sprawdzanie typów w Xcode 27.0 i w becie 27.1. Z flagą przechodzi je w becie, a w 27.0 kończy się tym samym błędem brakującego symbolu: zła kombinacja się nie zbuduje.14
Wersja samego SDK, odczytana przez kompilator. canImport przyjmuje drugi argument z podkreśleniem, który porównuje wersję modułu, a wersja modułu SwiftUI różni się między SDK: 8.0.84.1.104 w SDK 27.0, 8.0.85.27 w SDK 27.1, 8.1.6.1.101 w SDK bety 27.2.14 Ten wariant nie wymaga więc żadnego ustawienia kompilacji:
#if canImport(SwiftUI, _version: 8.0.85)
// ArrangementView, reservedRegions, onHingeChange, toolbarVerticalBehavior
#else
// what the app did before
#endif
Umieściłem #warning w każdej gałęzi i skompilowałem całość wszystkimi trzema Xcode: 27.0 wybrał drugą gałąź, beta 27.1 i beta 27.2 wybrały pierwszą.14 Zastrzeżenie kryje się w podkreśleniu. Gramatyka tego warunku w książce o Swifcie to canImport(import-path) i nic więcej, więc _version: jest funkcją kompilatora bez udokumentowanego kontraktu, a liczbę 8.0.85 odczytałem z dwóch SDK, a nie z publikacji Apple.14 Można z tego korzystać, dopóki sklep jest zamknięty dla 27.1, jeśli ustawienie kompilacji jest w danym projekcie niewygodne; flaga jest lepsza, jeśli potrzebne jest coś, czego da się bronić.
Tak czy inaczej, zapora jest tymczasowa. W dniu, w którym App Store Connect zacznie przyjmować kompilacje z Xcode zawierającego SDK 27.1, należy ją usunąć i zostawić sprawdzenia #available, bo to one chronią telefon, który wciąż ma iOS 27.0.
Wysyłka: co App Store Connect przyjmuje dziś
TestFlight przyjmuje kompilację 27.1. Noty wydania App Store Connect z 18 września: „You can now submit apps built with Xcode 27.1 beta using the SDK for iOS 27.1 beta or iPadOS 27.1 beta for internal and external testing.” (można już przesyłać aplikacje zbudowane w Xcode 27.1 beta z SDK iOS 27.1 beta lub iPadOS 27.1 beta do testów wewnętrznych i zewnętrznych). Wpisy z 16 i 28 września mówią to samo o Xcode 27.2 beta i beta 2.8 Kiradex trafia tam tą drogą; jej piąta kompilacja, ta testowana w tym wpisie, została przesłana 2 października, a App Store Connect wymienia ją jako poprawną.13
App Store jeszcze nie. Najnowszy wpis otwierający sklep pochodzi z 14 września: „You can now upload apps built with Xcode 27 using the SDK for iOS 27.0, iPadOS 27.0, macOS 27.0, tvOS 27.0, visionOS 27.0, and watchOS 27.0 for the App Store, and for internal and external testing through TestFlight.” (można już przesyłać aplikacje zbudowane w Xcode 27 z SDK w wersji 27.0 do App Store oraz do testów wewnętrznych i zewnętrznych w TestFlight).8 Nic późniejszego nie wspomina 27.1 i sklepu w jednym zdaniu, a kanał wydań Apple, którego najnowsze pozycje mają datę 28 września, wymienia jedną kompilację Xcode 27.1, betę z 18 września.8 Apple nie powiedział, kiedy to się zmieni. Urządzenie trafia do sprzedaży 23 października.1
Jeśli Apple nie otworzy sklepu dla SDK 27.1 przed 23 października, kompilacja ze sklepu, którą klienci będą mieli w dniu premiery, będzie w najlepszym razie kompilacją z SDK 27.0, a porównanie powyżej pokazuje, co taka kompilacja dostaje w symulatorze, przy czym prezentacja Apple opisuje ten sam środkowy poziom: ekran obok listwy stanu, poziome paski, brak zgięcia. To jest użyteczna aplikacja, o ile dobrze zmienia rozmiar, i to jest argument za tym, żeby pracę nad zmianą rozmiaru wypuścić już teraz, z Xcode 27.
Ekran startowy jest teraz obowiązkowy. To nie jest reguła dla Duo, ale przychodzi z tym samym SDK i kończy się błędem przy przesyłaniu, a nie przy recenzji. Nota techniczna Apple: „Starting in iOS 27 and iPadOS 27, App Store Connect requires your app to include a launch screen configuration in its Info.plist,” (od iOS 27 i iPadOS 27 App Store Connect wymaga, by aplikacja zawierała konfigurację ekranu startowego w swoim Info.plist), a bez jednego z kluczy UILaunchStoryboardName, UILaunchStoryboards, UILaunchScreen lub UILaunchScreens przesyłka zostaje odrzucona z komunikatem „ITMS-90870: Missing launch screen.”10 Kiradex deklaruje UILaunchScreen z kolorem, czerwienią swojej okładki, więc start płynnie przechodzi w animację otwarcia.13
Miejsca na zrzuty istnieją na papierze. Specyfikacje zrzutów ekranu w App Store Connect wymieniają iPhone Duo od 9 września, w dwóch parach: 1398 na 2034 lub 2034 na 1398 pikseli dla ekranu zewnętrznego oraz 2007 na 2853 lub 2853 na 2007 dla wewnętrznego, z adnotacją „Support for uploading assets for this device in App Store Connect will be available later this year.” (obsługa przesyłania materiałów dla tego urządzenia w App Store Connect będzie dostępna jeszcze w tym roku).9 Obowiązują zwykłe zasady: „You can upload one to 10 screenshots in .jpeg, .jpg, and .png formats,” (można przesłać od jednego do 10 zrzutów w formatach .jpeg, .jpg i .png) oraz „Images can’t include alpha channels or transparencies.” (obrazy nie mogą zawierać kanałów alfa ani przezroczystości).9
Jedno zdanie ze strony przesyłania przesądza o tym, jak to zaplanować: „Once your app is submitted for review and approved, you must create a new version to update the screenshots.” (gdy aplikacja zostanie wysłana do recenzji i zatwierdzona, aktualizacja zrzutów wymaga utworzenia nowej wersji).9 Zrzutów dla Duo nie da się dorzucić później osobno; gdy miejsca się otworzą, pojadą razem z wersją.
Podsumowując, kolejność, którą bym zastosował i którą stosuję przy Kiradex:
- Kompilacja 27.1 w TestFlight już teraz, z poprawkami ustaleń z przejścia przez pozy wprowadzanymi na bieżąco.
- Dla aplikacji, która już jest w sklepie: aktualizacja zbudowana w Xcode 27, zawierająca każdą poprawkę, która nie wymaga SDK 27.1. Klasy rozmiaru zamiast sprawdzeń idiomu i orientacji, obszary bezpieczne liczone osobno dla każdej krawędzi, paski należące do kontenerów systemowych, tytuł i symbol przy każdym elemencie paska narzędzi.
- Zrzuty w rozmiarach Duo zrobione już teraz, z symulatora, i odłożone.
- Wersja trzymana w gotowości na dzień, w którym spełnione będą dwa warunki: sklep przyjmie Xcode z SDK 27.1, a miejsca na zrzuty dla Duo przyjmą przesyłki. Każdą dotychczasową zmianę tego rodzaju Apple ogłaszał w notach wydania App Store Connect, w tym wpis z 14 września, który otworzył sklep dla wydania Xcode 27, i wpis z 9 września, który dodał specyfikacje zrzutów dla Duo, więc to tę stronę warto obserwować, razem ze stroną aktualności dla deweloperów.8
Jeszcze jeden wymóg czeka dalej. Od kwietnia 2027 roku „iOS and iPadOS apps must be built with the iOS 27 & iPadOS 27 SDK or later” (aplikacje na iOS i iPadOS muszą być zbudowane z SDK iOS 27 i iPadOS 27 lub nowszym), żeby w ogóle dało się je przesłać.18 Aplikacja wciąż budowana z SDK iOS 26 dostaje na Duo najmniejszy z trzech obrazów powyżej, a od kwietnia 2027 roku nie prześle aktualizacji, dopóki nie przejdzie na SDK iOS 27.
Zrzuty ekranu dla dwóch ekranów
Przejście przez pozy dostarczyło już surowego materiału: każdy przystanek uchwycono w 1398 na 2034 i 2853 na 2007 pikseli, a po obróceniu w 2034 na 1398 i 2007 na 2853, czyli we wszystkich czterech rozmiarach z wiersza iPhone Duo w App Store Connect.913 Pozostaje zdecydować, co je otacza, i właśnie tu składany telefon kusi do błędu.
Obraz, którego wszyscy chcą, to telefon do połowy otwarty, pod kątem, z aplikacją przelewającą się przez zgięcie. Wytyczne marketingowe Apple wykluczają go punkt po punkcie. O własnych obrazach urządzeń: „Use Apple product images ‘as is’ and without modification. Modifications include adding reflections, shadows, highlights, or graphic elements that appear to enter or come out of the product screen; cropping, tilting, or obstructing any part of the images; animating, flipping, or spinning the images” (obrazów produktów Apple należy używać w niezmienionej postaci: bez odbić, cieni, rozbłysków ani elementów wchodzących w ekran lub z niego wychodzących, bez kadrowania, przechylania, zasłaniania, animowania, odwracania i obracania). O obrazach wykonanych samodzielnie: „Straight-on product shots are preferred. Don’t use extreme angles or alter an Apple product in any way.” (preferowane są ujęcia produktu na wprost; nie należy stosować skrajnych kątów ani w jakikolwiek sposób zmieniać produktu Apple). A w sekcji Unauthorized Uses, na pierwszym miejscu listy: „Rendering in 3D or creating any simulation of an Apple product” (renderowanie w 3D lub tworzenie jakiejkolwiek symulacji produktu Apple).11 Mój wpis o zrzutach ekranu omawia, jak te zasady traktują nagradzane aplikacje i jak wygląda zestaw, który ich przestrzega; zawias niczego w nich nie zmienia.
W zamian Apple udostępnia pakiet ramek (bezels) dla tego telefonu, w dwóch wykończeniach i pięciu widokach: zamknięty telefon w pionie i w poziomie, otwarty ekran wewnętrzny w poziomie i w pionie oraz otwarty telefon od tyłu, z ekranem zewnętrznym obok kamer. Otwory w tych plikach mają dokładnie rozmiary zrzutów, więc zrzut z symulatora wchodzi bez skalowania.11 Nie ma widoku do połowy złożonego ani widoku pod kątem.
Dlatego kadry poniżej składają się z trzech elementów: tła w kolorach samej aplikacji, krótkiej linijki tekstu i zrzutu w ramce Apple, całego i prosto ustawionego, bez niczego na wierzchu. Różnorodność daje tło, wielkość urządzenia i jeden kadr w zestawie zupełnie bez urządzenia: pełnoekranowa karta aplikacji na czerni, która jest własnym 3D aplikacji, a nie niczyim sprzętem.

Trzy zestawy złożone skryptem ze zrzutów z przebiegu, w rozmiarach 1320 na 2868, 1398 na 2034 i 2853 na 2007 pikseli. Pokazują metodę, a nie stronę w sklepie: te zrzuty zawierają karty z katalogu, a to, co pokaże zestaw w sklepie, jest otwartym pytaniem z trzeciej uwagi poniżej.
Trzy praktyczne uwagi z ich budowania.
Składać skryptem. Zestawy powyżej powstają z jednego pliku Pythona, który bierze zrzut, nagłówek i tło, a zapisuje PNG w dokładnym rozmiarze, bez kanału alfa. Gdy aplikacja się zmienia, a ta zmieniła się dwa razy w dniu, w którym robiłem zrzuty, przebieg uruchamia się ponownie, a kadry się przebudowują.
Pokazywać to, co dodaje telefon. Strona przesyłania Apple mówi, że zestaw 6,9-calowy wystarcza, gdy interfejs jest taki sam na każdym rozmiarze: „provide only the highest resolution screenshots required. They automatically scale down to smaller device sizes.” (wystarczy dostarczyć zrzuty w najwyższej wymaganej rozdzielczości; zostaną automatycznie przeskalowane w dół dla mniejszych urządzeń).9 Na tym telefonie nie jest taki sam: ściana kart i dzielony inspektor istnieją tylko na ekranie wewnętrznym. To są dwa kadry, od których zaczyna się zestaw wewnętrzny.
Uważać na to, co jest na ekranie. Te same wytyczne mówią: „You are responsible for securing the rights to all materials used in screen content within your app.” (to na twórcy spoczywa obowiązek zapewnienia praw do wszystkich materiałów widocznych na ekranie w aplikacji).11 Aplikacja dla kolekcjonerów z natury pokazuje cudze grafiki, a strona w sklepie to marketing, czyli coś innego niż to, co aplikacja wyświetla w użyciu. Tej decyzji dla Kiradex jeszcze nie podjęliśmy, a powyższe kadry nie zostaną wysłane w obecnej postaci. Z tego powodu przebieg ma drugi tryb, działający na sześciu wymyślonych kartach; nie mają one jeszcze grafik, więc wysłany zestaw oznacza albo zaprojektowanie zastępników, albo uregulowanie praw.
Kiradex nie ma jeszcze strony w sklepie. Gdy ją dostanie, zacznie od zestawu 6,9-calowego, a zestawy dla Duo poczekają, z własną wersją, na dzień, w którym App Store Connect zacznie je przyjmować.
Przekazanie pracy agentowi programistycznemu
Większość tej pracy to rodzaj zadań, z którymi agent radzi sobie dobrze, pod warunkiem że widzi aplikację. Są dwie połowy, a jedną z nich dostarcza Apple.
Połowa statyczna należy do Apple. Pierwsza Tech Talk kończy się właśnie nią: „During the talk, Modernize Your UIKit App, we introduced a new app modernization skill. With Xcode 27.1, this skill has a new name: App Resizability. It now supports SwiftUI and iPhone Duo.” (9:19) (w prezentacji Modernize Your UIKit App przedstawiliśmy nową umiejętność modernizacji aplikacji; w Xcode 27.1 nosi ona nową nazwę, App Resizability, i obsługuje teraz SwiftUI oraz iPhone Duo).3 Ta umiejętność to zestaw zwykłych plików tekstowych wewnątrz bety: w Xcode 27.1 beta jest to Contents/PlugIns/IDEIntelligenceChat.framework/Versions/A/Resources/app-resizability.idechatprompttemplate i pięć plików referencyjnych obok.15 Jej instrukcje mówią, jak szeroko zarzucić sieć: „Treat a request about the foldable iPhone Duo as a request for every task in the Task Registry, because a screen that changes size exposes all of them at once.” (prośbę dotyczącą składanego iPhone Duo należy traktować jako prośbę o każde zadanie z Task Registry, bo ekran zmieniający rozmiar odsłania je wszystkie naraz).15
Warto ją przeczytać, nawet jeśli nigdy się jej nie uruchomi, bo to spisana lista kontrolna przeglądu Apple. Sprawdza trzy ustawienia projektu i żadnego nie zmienia (klucz ekranu startowego, deklarację orientacji na iPadzie, UIRequiresFullScreen), a potem szuka pięciu wzorców: UIScreen.main, układu zależnego od orientacji interfejsu, układu zależnego od userInterfaceIdiom, cyklu życia aplikacji tam, gdzie powinien być cykl życia scen, oraz kodu obszaru bezpiecznego, który zakłada, że obie strony są równe. Plik o obszarze bezpiecznym zawiera zdanie, które wyjaśnia połowę tego, co psuje się na tym telefonie: „Asymmetric horizontal insets are the normal case. Where a vertical bar is present, one horizontal edge usually carries the whole inset and the other carries zero.” (asymetryczne wcięcia poziome są normą; tam, gdzie jest pionowy pasek, jedna pozioma krawędź zwykle niesie całe wcięcie, a druga zero).15
Kiradex to aplikacja SwiftUI napisana w tym roku i tych pięć wyszukiwań nic w niej nie znajduje.13 Każde ustalenie powyżej wzięło się z jej uruchomienia. Na tym polega granica połowy statycznej: czyta kod źródłowy, a zgięcie, listwa i klawiatura są widoczne tylko na ekranie.
Druga połowa to przejście, które agent może uruchomić i obejrzeć. Audyt powyżej umożliwiły trzy małe elementy i żaden z nich nie jest specyficzny dla tej aplikacji:
- Test UI, który odwiedza każdy rodzaj ekranu i zatrzymuje się na każdym. Bez asercji; to wycieczka. Nasza otwiera Dex, zestaw, kartę, arkusz, listę kolekcji, kartę z kolekcji, pełnoekranową przeglądarkę i wyszukiwanie z wysuniętą klawiaturą: osiem przystanków.13
- Zrzut wykonywany na Macu, a nie w teście. Zrzut wykonany przez sam test UI obejmuje jeden ekran.
simctlsięga do obu:
xcrun simctl io "$UDID" screenshot --type=png --display=primary outer.png
xcrun simctl io "$UDID" screenshot --type=png --display=primary-1 inner.png
Test zapisuje pusty plik nazwany od przystanku; pętla powłoki na Macu go zauważa, robi zrzut obu ekranów i odpowiada drugim plikiem; test na niego czeka i idzie dalej. Zrzut zewnętrzny ma 1398 na 2034 piksele przy zamkniętym telefonie, a wewnętrzny 2853 na 2007 przy otwartym, więc obrazy z audytu i zrzuty do sklepu powstają w jednym przebiegu.913
3. Sposób na zmianę pozy bez ręki na myszy. simctl nie ma polecenia do póz, a frameworki testów UI w tej becie nie mają wywołania dla zawiasu, które udałoby mi się znaleźć, więc skrypt naciska przyciski Closed, Book, Open i Rotate Right w Device Hub przez API dostępności, co działa także z Device Hub w tle.13
Dzięki nim sprawdzanie aplikacji w każdej pozie przestaje być prośbą o opinię agenta, a staje się folderem obrazów dla każdej pozy, który może przeczytać zarówno agent, jak i człowiek. Poniższy brief to ten, który bym przekazał; jest po angielsku, bo został napisany do wklejenia wprost do anglojęzycznego agenta programistycznego.
Goal: make this app correct on iPhone Duo in every pose, without device checks.
0. Toolchain. Build with Xcode 27.1 beta. Confirm the binary is stamped with the 27.1 SDK:
otool -l <App>.app/<App> | grep -A4 LC_BUILD_VERSION (debug builds: <App>.debug.dylib)
If "sdk" is lower than 27.1, stop: nothing below will reproduce.
1. Static pass. Report every use, with file and line, of:
UIScreen.main / UIScreen.mainScreen; userInterfaceIdiom; interface orientation used for layout;
a UIApplicationDelegate doing scene work; one safe-area inset applied to both sides;
a bare ignoresSafeArea() on anything a person reads or taps; fixed widths tied to a phone size;
toolbars or tab bars built by hand instead of owned by NavigationStack, NavigationSplitView or TabView;
toolbar items with a title and no symbol, or a symbol and no title.
Confirm Info.plist has a launch screen key and no orientation lock the design does not need.
2. Walk. Run the screenshot tour in each pose and capture BOTH displays at every stop:
closed; closed and turned; open; open and turned; partly folded; partly folded and turned.
If no tour exists, write a UI test that stops at each kind of screen and signals a host script, and have
the script capture with: xcrun simctl io <udid> screenshot --display=primary (outer)
xcrun simctl io <udid> screenshot --display=primary-1 (inner)
Poses are buttons in Device Hub (Closed, Book, Open, Rotate Right); simctl has no pose command.
3. Read every capture and answer, per pose:
- Are the bars where the system puts them (down the side closed and in open landscape, across the top
and bottom in open portrait)? Is any toolbar item missing from the bar and from the overflow menu?
- Does any sheet reserve the side rail and leave it empty?
- With the keyboard up, what is covered? Can every tab still be reached once it is dismissed?
- Does anything sit under the outer camera corner or the status column?
- Open: does a grid have an even number of columns? Does any control or line of text cross the middle?
- Partly folded: does content move off the fold? Do sheets and alerts land on one side?
- Turned: did a two-pane layout stack when it should have stayed side by side, or the reverse?
- Is the same selection, scroll position and navigation path still there after the pose changed?
4. Fix with, in this order: a system container that already adapts; size classes; ArrangementView for a
custom two-pane layout; reservedRegions for hand-placed content. Never branch on the device model,
the idiom, the orientation, or the raw hinge angle to decide layout.
5. Guard everything from the 27.1 SDK with `if #available(iOS 27.1, *)` and a fallback that keeps both
panes reachable. If the same source must also build with Xcode 27.0, fence it at compile time.
6. Report what could not be checked in the simulator: cameras, StandBy, extensions, haptics, real reach.
Materiały Apple w kolejności, w jakiej bym z nich korzystał
Wszystko, co Apple opublikował dla tego urządzenia, wychodzi z jednej strony, Get ready for iPhone Duo.19 W kolejności roboczej:
| Co | Po co to otworzyć |
|---|---|
| Prepare your app for iPhone Duo (Tech Talk) | Trzy poziomy SDK, klasy rozmiaru, obszary bezpieczne. Od tego należy zacząć |
| Preparing your app for iPhone Duo (przewodnik) | Ten sam materiał w formie tekstu, z nazwą każdego API. Cztery sprawdzenia z sekcji „Address common layout and resizing considerations” to lista do audytu2 |
| Raise the bar with iPhone Duo | Pionowe paski: co w nich umieścić, co zostaje poza nimi, przepełnienie |
| Strike a pose with adaptive layouts on iPhone Duo | Zgięcie: przesunięcie, zarezerwowane regiony, widoki układu |
| Designing for iPhone Duo (HIG) i Design for iPhone Duo | Zasady, których będzie wymagał projektant7 |
| Leverage multiple displays and scenes on iPhone Duo | Zawias, Split View, druga scena na ekranie zewnętrznym |
| Build a great camera experience for iPhone Duo | Tylko przy nagrywaniu obrazu: dwie przednie kamery i kierunek, w którym patrzy każda z nich6 |
| Nagrania Group Lab, dzień 1 i dzień 2, oraz pytania i odpowiedzi na forum dotyczące SwiftUI, UIKit oraz Photos and Camera | Inżynierowie Apple odpowiadający na pytania deweloperów19 |
| Apple Design Resources | Zestawy do Figmy i Sketcha oraz ramki produktów do materiałów marketingowych11 |
| Poza Apple: przewodnik po symulatorze od SwiftLee, iPhone Duo by Examples, lista kontrolna BleepingSwift, przewodnik Adapty | Lista testów i suwak zawiasu; jeden uruchamialny przykład na każde API, z notatkami terenowymi; krótka lista kontrolna; jedyny znaleziony przeze mnie materiał, który przerabia paywall17 |
| Warsztaty | Stacjonarne. SwiftLee opisuje je jako połączone „with the opportunity to test your app on a physical device,” (z możliwością przetestowania aplikacji na fizycznym urządzeniu), co przed 23 października jest jedynym sposobem na sprawdzenie kamery1719 |
Nie przeczytałem spisu pytań i odpowiedzi z Group Lab ani wątków na forum: strony forum Apple odpowiadają na automatyczne pobieranie stroną weryfikacji człowieka, a ja jej nie obchodziłem.
Najważniejsze wnioski
- Dla tych, którzy już wydają aplikację: pracę nad zmianą rozmiaru warto wypuścić teraz, zbudowaną w Xcode 27. To właśnie klienci będą mieli na Duo 23 października, jeśli tego dnia sklep będzie nadal zamknięty dla SDK 27.1, a nic z tego nie wymaga bety.
- Dla tych, którzy wdrażają API Duo: budować w Xcode 27.1 beta, potwierdzić
sdk 27.1lub nowszy poleceniemotool, trzymać kompilację w TestFlight i odgrodzić wywołania wymagające 27.1, jeśli ten sam kod wciąż musi się budować dla sklepu. - Dla testujących: nie czytać kodu, tylko uruchamiać pozy. Zamknięty, otwarty, częściowo złożony, każdy z nich obrócony, arkusz, klawiatura, widok pełnoekranowy i jeden ekran otwarty w chwili rozkładania. Za każdym razem robić zrzuty obu ekranów.
- Dla przygotowujących stronę w sklepie: robić zrzuty w rozmiarach Duo już teraz, składać kadry skryptem, używać ramek Apple na wprost i trzymać wersję w gotowości na dzień, w którym miejsca się otworzą.
- Dla przekazujących to agentowi: dać mu przejście przez pozy, a nie tylko pliki. Umiejętność App Resizability od Apple obejmuje to, co da się znaleźć czytaniem; wszystko w ustaleniach powyżej zostało znalezione patrzeniem.
Często zadawane pytania
Czy moja obecna aplikacja działa na iPhone Duo bez zmian?
Tak. Prezentacja Apple obiecuje to dla każdego SDK, a symulator to potwierdza: kompilacja ze znacznikiem SDK iOS 26 działała jako okno 375 na 667 punktów, a kompilacja ze znacznikiem 27.0 wypełniła ekran obok listwy stanu, z poziomymi paskami. Żadna z nich nie dostaje pionowych pasków ani zarezerwowanych regionów.312
Którego Xcode potrzebuję do pełnego układu iPhone Duo?
Xcode 27.1 beta (27A9269), który zawiera SDK iOS 27.1 i jedyny symulator iPhone Duo. Jego runtime symulatora 27.1 obsługuje wyłącznie typ urządzenia iPhone Duo, więc inne iPhone’y testuje się na runtimie 27.0. SDK z Xcode 27.2 beta ma te same API, a sonda ze znacznikiem 27.2 zachowywała się w symulatorze jak 27.1, ale ten Xcode nie ma Duo, na którym dałoby się ją uruchomić.81214
Czy mogę dziś wysłać kompilację dla iPhone Duo do App Store?
Nie taką, która została zbudowana z SDK 27.1, według stanu na 2 października 2026 roku. App Store Connect przyjmuje kompilacje z bet Xcode 27.1 i 27.2 do wewnętrznych i zewnętrznych testów w TestFlight, a do sklepu kompilacje z Xcode 27. Apple nie podał daty zmiany.8
Jakich rozmiarów zrzutów ekranu wymaga App Store Connect dla iPhone Duo?
1398 na 2034 lub 2034 na 1398 pikseli dla ekranu zewnętrznego oraz 2007 na 2853 lub 2853 na 2007 dla ekranu wewnętrznego, od jednego do dziesięciu obrazów bez kanału alfa. Przesyłanie jest zapowiedziane na „later this year” (jeszcze w tym roku).9
Jak zrobić zrzuty obu ekranów symulatora iPhone Duo?
xcrun simctl io <udid> screenshot --display=primary dla ekranu zewnętrznego i --display=primary-1 dla wewnętrznego. Zrzut wykonany przez sam test UI obejmuje jeden ekran.13
Dlaczego paski mojej aplikacji są w symulatorze iPhone Duo nadal poziome?
Trzy przyczyny, w kolejności, w jakiej należy je sprawdzać. Plik binarny nie ma znacznika SDK 27.1. Paski są zbudowane ręcznie, zamiast należeć do TabView, NavigationStack lub NavigationSplitView. Albo ekran wewnętrzny jest w pionie, gdzie Apple celowo zostawia paski poziome.2712
Czy potrzebuję osobnego układu dla każdej pozy?
Nie. Wytyczne Apple to dwa układy, dla szerokości compact i regular, plus reakcja na zgięcie tam, gdzie treść by przez nie przechodziła. Kiradex ma te dwa układy i jeden widok układu; poza Book nie wymagała żadnego kodu.713
Powiązane na tej stronie: wpis o symulatorze zawiera kroki instalacji, profil urządzenia i poprawione pomiary dla każdej pozy; projektowanie dla iPhone Duo odczytuje wytyczne projektowe Apple jako zasady; wpis o Duo dla deweloperów zawiera dane sprzętowe i datowaną historię; wpis o zrzutach ekranu uzasadnia, co powinien mówić zestaw; lista kontrolna dla iPhone’a o zmiennym rozmiarze to praca w Xcode 27, którą ten wpis każe wypuścić najpierw; a centrum Xcode 27 śledzi narzędzia.
Źródła
-
Apple Newsroom, Apple unveils iPhone Duo, 9 września 2026, dostęp 2 października 2026: „Pre-orders begin Friday, October 16, with availability beginning Friday, October 23.” (przedsprzedaż rusza w piątek 16 października, a dostępność w piątek 23 października) oraz „iPhone Duo will be available with iOS 27.1.” (iPhone Duo będzie dostępny z iOS 27.1). ↩↩↩
-
Apple, Preparing your app for iPhone Duo, Technology Overviews, pobrane przez endpoint JSON dokumentacji 2 października 2026; cytowane są Overview oraz sekcje „Address common layout and resizing considerations”, „Organize items in your bars” i „Arrange views in different poses”. Zdanie z Overview o wersjach Xcode brzmiało inaczej, gdy ta strona cytowała je 17 września 2026 („Build your app with Xcode 27.1 or later to use all of the available screen space on iPhone Duo. In earlier versions, your app doesn’t extend under the status bar and camera.”); wpis o Duo dla deweloperów na tej stronie odnotował obecne brzmienie 19 września. Strona nie zawiera żadnej informacji o zmianach. ↩↩↩↩↩↩
-
Apple Developer Tech Talk, Prepare your app for iPhone Duo, David Jackson, UI Frameworks. Cytaty pochodzą z angielskiej ścieżki napisów prezentacji, z podanych znaczników czasu. ↩↩↩↩
-
Apple Developer Tech Talk, Raise the bar with iPhone Duo, Anna, inżynierka UI Frameworks, i Maria, Human Interface Designer. Cytaty pochodzą z angielskiej ścieżki napisów prezentacji, z podanych znaczników czasu. ↩↩↩
-
Apple Developer Tech Talk, Strike a pose with adaptive layouts on iPhone Duo, Maria, Human Interface Designer, i Harry, inżynier UI Frameworks. Cytaty pochodzą z angielskiej ścieżki napisów prezentacji, z podanych znaczników czasu. ↩↩↩
-
Apple Developer Tech Talks, Leverage multiple displays and scenes on iPhone Duo i Build a great camera experience for iPhone Duo, cytaty z angielskich ścieżek napisów z podanych znaczników czasu; Apple, Choosing a camera by the direction it faces, AVKit, dostęp 2 października 2026. ↩↩↩
-
Apple, Designing for iPhone Duo, Human Interface Guidelines, pobrane przez endpoint JSON dokumentacji 2 października 2026; cytowane są sekcje „Device poses” i „Vertical controls”. ↩↩↩↩↩
-
Apple, App Store Connect release notes, dostęp 2 października 2026: cytowane są wpisy z 14 i 18 września 2026; wpis z 9 września dodaje specyfikacje zrzutów ekranu dla iPhone Duo i mówi, że ich przesyłanie „will be available later this year”, czyli zdanie powtarzane przez stronę specyfikacji; wpisy z 16 i 28 września otwierają TestFlight dla Xcode 27.2 beta i beta 2 w tej samej formie, dla sześciu platform; żaden wpis datowany po 18 września nie wymienia Xcode 27.1 ani SDK iOS 27.1. Apple, Releases, kanał RSS pobrany 2 października 2026, data ostatniej kompilacji Mon, 28 Sep 2026 14:00:00 PDT: jedna pozycja wymienia Xcode 27.1, „Xcode 27.1 beta (27A9269)”, z datą Fri, 18 Sep 2026; najnowsza pozycja dotycząca Xcode to „Xcode 27.2 beta 2 (27B5028f)”, z datą Mon, 28 Sep 2026. ↩↩↩↩↩↩↩↩↩↩↩
-
Apple, Screenshot specifications i Upload app previews and screenshots, pomoc App Store Connect, dostęp 2 października 2026, cytowane. ↩↩↩↩↩↩↩↩↩↩
-
Apple, TN3208: Preparing your app’s launch screen to meet App Store requirements, dostęp 2 października 2026, cytowane; historia zmian: „2026-09-14 Updated the ITMS-90870 error message to reflect the iOS 27 launch screen requirement.” oraz „2026-06-08 First published.” ↩↩↩
-
Apple, Marketing Resources and Identity Guidelines, sekcje „Apple Product Images”, „Unauthorized Uses”, „Screen Content” i „Custom Photography and Video”, dostęp 2 października 2026, cytowane. Apple, Apple Design Resources, Product Bezels, iPhone Duo (Photoshop i PNG), dostęp 2 października 2026. Pomiary ramek są autora, na podstawie plików PNG z
Bezel-iPhone-Duo.dmgod Apple: „Outer Closed Portrait” ma 1574 na 2194 piksele z przezroczystym otworem 1398 na 2034; „Inner Open Landscape” ma 3093 na 2247 z otworem 2853 na 2007; pakiet zawiera też „Inner Open Portrait”, „Outer Closed Landscape” i „Outer Open”, każdy w wariantach Star White i Night Sky. Wycięcie na kamerę w „Outer Closed Portrait”, zmierzone wewnątrz otworu przy trzech pikselach na punkt, rozciąga się od 400,3 do 436,3 punktu w poziomie i od 29,7 do 65,7 w pionie; przesłonięcie kamery w sondzie rozciąga się od 399 do 436 i od 30 do 67. ↩↩↩↩↩↩ -
Przebiegi autora z 2 października 2026: macOS 27.0 (26A428), Xcode 27.1 beta (27A9269), runtime symulatora iOS 27.1 (24A94401) i symulator utworzony z typu urządzenia iPhone Duo. Sonda, DuoProbe2, to jeden plik Swift:
TabView, którego pierwsza karta zawieraNavigationStackz pięcioma elementami paska narzędzi, odczyt rozmiaru zGeometryProxy, klas rozmiaru,toolbarVerticalEdge,onHingeChangeireservedRegionsobu rodzajów z.includeInactive, odczytywanych przy każdej ewaluacji body i przeliczanych co sekundę,ArrangementVieww stylu dzielonym oraz widok UIKit logujący swoje okno, ekran swojej sceny okna,UIScreen.maini cechęverticalBarEdge. Skompilowano ją trzy razy z tego pliku przezswiftcz SDK symulatora 27.1, z docelową wersją wdrożenia 27.1, wskazując linkerowi, jaką wersję SDK ma zapisać (-Xlinker -platform_version -Xlinker ios-simulator -Xlinker 27.1 -Xlinker <26.0, 27.0 or 27.1>);otool -lna każdym pliku binarnym wypisał odpowiadającą wartośćsdk. Pozy ustawiano przyciskami Closed, Book, Open i Rotate Right w Device Hub, naciskanymi przez API dostępności. Linie konsoli, znacznik 27.1, zamknięty:size=382x562 ... h=compact v=regular verticalEdge=trailing safe=EdgeInsets(top: 82.0, leading: 0.0, bottom: 34.0, trailing: 84.0) divisions=0 occlusions=2,occlusion[0] active=true frame=(399,-52 37x37),occlusion[1] active=true frame=(382,-82 84x170),window=(466.0, 678.0),verticalBarEdge=2; otwarty:size=867x553 ... h=regular v=regular verticalEdge=trailing ... divisions=1 occlusions=2,division[0] active=false frame=(455,-82 40x669) margins=EdgeInsets(top: 0.0, leading: 20.0, bottom: 0.0, trailing: 20.0),occlusion[0] active=false frame=(677,-61 58x37),occlusion[1] active=true frame=(867,-82 84x120),window=(951.0, 669.0),hinge=fullyOpen 180 deg; Book: to samo zdivision[0] active=trueihinge=partiallyOpen 127 deg; otwarty i obrócony:size=669x734 ... verticalEdge=nil ... divisions=1 occlusions=2,division[0] active=false frame=(0,321 669x40),window=(669.0, 951.0),mainScreen=(466.0, 678.0),verticalBarEdge=0; zamknięty i obrócony:size=594x350 ... h=compact v=compact verticalEdge=trailing,window=(678.0, 466.0). Ramki podano we współrzędnych widoku odczytu, którego początek leży 82 lub 134 punkty poniżej górnej krawędzi okna. Znacznik 27.0:window=(386.0, 678.0)zamknięty,(871.0, 669.0)otwarty,(669.0, 871.0)otwarty i obrócony,(678.0, 386.0)zamknięty i obrócony, zverticalEdge=nilorazdivisions=0 occlusions=0w każdej linii i w każdej pozie. Znacznik 26.0:window=(375.0, 667.0)zamknięty, otwarty, w Book oraz otwarty i obrócony, a(667.0, 375.0)zamknięty i obrócony, przez cały czas zh=compact. Przy każdym uruchomieniu z 27.1 pierwsze sześć do dziewięciu ewaluacji zalogowałodivisions=0 occlusions=0, zanim pojawiły się regiony, w tym trzy, zanim widok miał rozmiar. Położenia paneli w pozach Open i Book zmierzono na zrzutach: podstawowy od x 8 do 433,7, a drugorzędny od 433,7 do 859 na płasko; podstawowy do 455,7, pusty pas do 495,7, drugorzędny do 859 w Book. Arkusze, zamknięty: treść374x562z czysto tekstowym Done, to samo z symbolem na Done,450x428iverticalEdge=nilz.toolbarVerticalBehavior(.disabled); otwarty:653x501wyśrodkowany zh=compact; Book:459x501przy krawędzi początkowej. Przy widoku układu wypełniającym obszar treści (opcja uruchomienia) zwykły.splitumieścił na obróconym ekranie panel podstawowy nad drugorzędnym, a.split.axes(.horizontal)pokazał sam panel podstawowy; otwarty i płaski ten sam widok podzielił się na boki, a w Book zostawił pas zgięcia pusty. Sonda skompilowana tak, jak opisuje wpis z 21 września (swiftc -sdkprzy nieustawionymSDKROOT), wypisałaclang: warning: using sysroot for 'macOS 27.0' but targeting 'arm64-apple-ios27.1.0-simulator'i dostała znaczniksdk 27.0. Uruchomiono jeszcze dwie kompilacje, w stanie zamkniętym i otwartym. PlainProbe, z tym samym widokiem kart, stosem nawigacji i paskiem narzędzi, bez niczego z SDK 27.1, skompilowana przez Xcode 27.0 (27A266a) z jego własnym SDK iOS 27.0 (otool:minos 27.0,sdk 27.0):window=(386.0, 678.0)w stanie zamkniętym i(871.0, 669.0)w otwartym. DuoProbe2 ze znacznikiemsdk 27.2: te same linie co przy znaczniku 27.1 w obu pozach.simctl list runtimes -jpodajesupportedDeviceTypesruntime’u 27.1 jako jedną pozycję, iPhone Duo, asimctl createz typem iPhone 18 Pro Max na tym runtimie kończy się błędem „Incompatible device”. ↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩ -
Kiradex to aplikacja autora (941 Apps), wersja 1.0, kompilacja 5, przesłana do TestFlight 2 października 2026 i tego samego dnia oznaczona przez App Store Connect jako poprawna. Fakty o projekcie pochodzą z jego kodu źródłowego w tej kompilacji: docelowa wersja wdrożenia iOS 27.0, zbudowana z SDK 27.1 (
otool -lna pliku binarnym aplikacji:minos 27.0,sdk 27.1),UILaunchScreenz kolorem, orientacja pionowa i obie poziome,TabViewz pięcioma kartami i dwa miejsca z#available(iOS 27.1, *), jedno wokółArrangementView, drugie wokółonHingeChange. Linijka z roadmapy jest cytowana z własnych notatek projektu. Przejście to test UI, który zatrzymuje się na ośmiu rodzajach ekranu i prosi skrypt na hoście o zrzut symulatora poleceniamisimctl io <udid> screenshot --display=primaryi--display=primary-1; działał w sześciu pozach na symulatorze iPhone Duo (runtime iOS 27.1), ze wszystkimi ośmioma przystankami w pięciu z nich i siedmioma przy telefonie zamkniętym i obróconym, oraz na symulatorze iPhone 18 Pro Max (runtime iOS 27.0, pion i poziom). Rozmiary zrzutów: 1398 na 2034 i 2034 na 1398 (zewnętrzny), 2853 na 2007 i 2007 na 2853 (wewnętrzny), 1320 na 2868 (6,9 cala). Lewą krawędź inspektora zmierzono na zrzutach ekranu wewnętrznego: x 433,7 na płasko i 495,7 w pozie Book. Test rozkładania uruchomił aplikację w stanie zamkniętym, nagrywał ekran wewnętrzny w sposób ciągły i nacisnął Open; cztery kolejne klatki pokazują animację otwarcia. Test karty przy rozkładaniu otworzył kartę w stanie zamkniętym, nacisnął Open i zrobił zrzut dwadzieścia sekund później. Test przeglądarki otworzył pełnoekranową przeglądarkę cztery razy w jednej sesji na 6,9-calowym symulatorze i zmierzył każdy zrzut: pierwszy miał 52 procent pikseli innych niż czarne, pozostałe trzy 0,3 procent. Wyszukiwanie tekstowe we frameworkachXCTestiXCUIAutomationw platformie symulatora Xcode 27.1 beta haseł „hinge”, „posture”, „DevicePose” i „foldState” nic nie znalazło, asimctlnie wymienia polecenia do póz. ↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩ -
Test autora z 2 października 2026. Plik używający
ArrangementViewzaif #available(iOS 27.1, *)sprawdzono poleceniemswiftc -typecheckz SDK symulatora każdego zainstalowanego Xcode: Xcode 27.0 (27A266a) zakończył się błędemerror: cannot find 'ArrangementView' in scope; Xcode 27.1 beta (27A9269) i Xcode 27.2 beta (27B5019j) przeszły. Ten sam plik odgrodzony przez#if DUO_SDKprzeszedł w 27.0 bez flagi i w becie 27.1 z flagą i bez niej, a w 27.0 z-D DUO_SDKsię nie powiódł. Odgrodzony przez#if canImport(SwiftUI, _version: 8.0.85)przeszedł we wszystkich trzech, a#warningw każdej gałęzi pokazał, że 27.0 kompiluje wariant zastępczy, a obie bety gałąź 27.1.xcrun swift --versionwypisujeApple Swift version 6.4 (swiftlang-6.4.0.34.1 clang-2100.3.34.1)we wszystkich trzech. Wersje modułu SwiftUI to wartości-user-module-versionwSwiftUI.swiftinterfacekażdego SDK. Zainstalowana tu beta 27.2 to beta 1 (27B5019j); jej runtime symulatora iOS 27.2 (24B5084k) nie wymienia typu urządzenia iPhone Duo, a noty Apple dla 27.2 odsyłają po niego do bety 27.1. Gramatyka warunku pochodzi z The Swift Programming Language, Statements, „Conditional Compilation Block”, dostęp 2 października 2026: „platform-condition →canImport(import-path)”. ↩↩↩↩↩↩↩↩↩ -
Xcode 27.1 beta (27A9269),
Contents/PlugIns/IDEIntelligenceChat.framework/Versions/A/Resources/:app-resizability.idechatprompttemplateorazapp-resizability-ref-uiscreen-task.md.packaged,-orientation-task,-scene-lifecycle-task,-safe-area-taski-idiom-task, przeczytane 2 października 2026; cytaty pochodzą z sekcji „When to Use” szablonu i z reguły 6 pliku referencyjnego o obszarze bezpiecznym; trzy sprawdzenia projektu to jego tabela „Prerequisites”, a pięć wzorców to jego „Task Registry”. Xcode 27.0 (27A266a) ma w tym samym folderzeuikit-app-modernization.idechatprompttemplatei cztery pliki referencyjne. ↩↩↩ -
Apple, dokumentacja pobrana przez endpoint JSON 2 października 2026: ArrangementView, reservedRegions(kind:options:layoutDirectionBehavior:), onHingeChange(isEnabled:_:), toolbarVerticalBehavior(_:) i toolbarVerticalEdge. ↩
-
Antoine van der Lee, iPhone Duo Simulator: Testing and optimizing your SwiftUI app, SwiftLee, 22 września 2026, cytowane. Artem Novichkov, iPhone Duo by Examples, README na GitHubie, „Good to Know”, dostęp 2 października 2026: „Its frame is the same in both states: 40 pt wide, with 20 pt margins on each side of a zero-width fold line.”, „Reserved regions arrive after the first layout pass.” oraz „When folded, the outer display has no reserved regions at all, not even inactive ones.” Dwa pierwsze zgadzają się z sondą z tego wpisu; trzecie nie, bo sonda odczytała na zamkniętym ekranie zewnętrznym dwa aktywne przesłonięcia. Mick MacCallum, How to Get Your App Ready for iPhone Duo, BleepingSwift, 18 września 2026. Yurii Kleimenov, How to adapt your iOS app to iPhone Duo, Adapty, opublikowane 11 września 2026, oznaczone jako zaktualizowane 15 września. ↩↩↩↩↩
-
Apple, „App Store submissions now open for the latest OS releases”, aktualności dla deweloperów, 9 września 2026: od kwietnia 2027 roku aplikacje przesyłane do App Store Connect „need to meet the following minimum requirements” (muszą spełniać następujące wymagania minimalne), z których pierwsze brzmi „iOS and iPadOS apps must be built with the iOS 27 & iPadOS 27 SDK or later”. ↩
-
Apple, Get ready for iPhone Duo, dostęp 2 października 2026: sześć Tech Talks, dwa nagrania Group Lab, link do pytań i odpowiedzi z Group Lab, pytania i odpowiedzi na forum dotyczące Photos and Camera, SwiftUI i UIKit, Xcode 27.1 beta, wytyczne i zasoby projektowe, przewodnik przygotowawczy oraz warsztaty stacjonarne. Strony z pytaniami i odpowiedziami z Group Lab ani wątków forum nie przeczytano; żądania do nich zwracały stronę weryfikacji człowieka. ↩↩↩
-
Apple, Xcode 27.1 Beta Release Notes, pobrane przez endpoint JSON dokumentacji 2 października 2026, Simulator, Known Issues: „StandBy is unavailable in the iPhone Duo Simulator runtime. (187708663)” oraz „Running and debugging most app extensions is unavailable in the iPhone Duo Simulator runtime. (187708767)”. Apple, Xcode 27.2 Beta 2 Release Notes, pobrane w ten sam sposób 2 października 2026: Overview, „Download Xcode 27.1 beta to get the iOS SDK and simulator support for iPhone Duo.”; General, Known Issues, 187146039, cytowane. ↩