On September 9 Apple unveiled the iPhone Duo — its first foldable iPhone. Users are busy arguing about the $1999 price and the under-display camera; what we developers got is six Tech Talks, an HIG page, and a promise of an Xcode 27.1 beta by the end of the month. I watched all six talks and collected here the work almost every app will have to do — with code in both Swift and Objective-C, because the UIKit side of the new APIs is callable from both languages, and there are far more legacy codebases out there than anyone wants to believe.
A quick caveat about accuracy. The device ships October 23, and as I write this, Xcode 27.1 is still "coming later this month". Every signature below comes from the official Tech Talks, but until you check them against the SDK headers, treat them as the shape of the API rather than letter-perfect spelling.
A size continuum, not a new idiom#
The first thing Apple repeats in nearly every talk: iPhone Duo is not a "new device class" that needs its own interface. It's still an iPhone; the range of available sizes just got wider.
Here are the specifics. The outer display (5.4″) behaves like a regular iPhone: compact width, the usual orientations. The inner one (7.6″) is nearly an iPad: regular × regular in every orientation. And here's the detail that will break the most apps: the inner display ignores supportedInterfaceOrientations. An app locked to portrait will rotate on the inner screen. There is no way to prevent it.
| Configuration | Horizontal | Vertical |
|---|---|---|
| Outer screen, portrait | compact | regular |
| Outer screen, landscape | compact | compact |
| Inner screen, any orientation | regular | regular |
Which leads to the main rule: every branch on orientation or device idiom (userInterfaceIdiom, "if iPad, show two columns") turns into a defect. The only valid thing to branch on is size classes:
// SwiftUI
@Environment(\.horizontalSizeClass) private var hSizeClass
var body: some View {
if hSizeClass == .regular {
TwoColumnLayout()
} else {
SingleColumnLayout()
}
}// Objective-C: same question, asked through the trait collection
- (void)traitCollectionDidChange:(UITraitCollection *)previousTraitCollection {
[super traitCollectionDidChange:previousTraitCollection];
BOOL isWide = self.traitCollection.horizontalSizeClass ==
UIUserInterfaceSizeClassRegular;
[self applyLayoutForWideMode:isWide];
}If your codebase has a branch whose meaning is "is this an iPhone Duo" — that's a signal to stop and rephrase it as "how much space do I have right now".
Three SDK tiers: what a rebuild buys you#
How your app behaves on the Duo depends on which SDK it was built against. There are three tiers:
- Pre-iOS 27 SDK. Runs unchanged, but letterboxed: on the closed device the content stops short of the status bar and camera; on the open one you get the familiar size with margins.
- iOS 27 SDK. Content extends into the status bar area on the inner display.
- iOS 27.1 SDK (Xcode 27.1). Full edge-to-edge, system bars automatically rearrange vertically, and the reserved regions and arrangements APIs unlock.
Rebuilding against 27.1 is the cheapest and most effective change of all the ones available. Without it, the rest of the adaptation simply isn't accessible.
Hunting down baked-in assumptions#
Every foldable-port bug is some fixed assumption in the code. Here are three worth grepping for today.
UIScreen.main is dead. On a device with two screens, "the main screen" is an ambiguous concept, and Apple says outright the API is headed for deprecation. Replacements:
// Before
let scale = UIScreen.main.scale
// After
let scale = traitCollection.displayScale
// If you genuinely need the screen
let screen = view.window?.windowScene?.screen// Objective-C
CGFloat scale = self.traitCollection.displayScale;
UIScreen *screen = self.view.window.windowScene.screen;Symmetric inset math. Safe areas on the Duo are routinely asymmetric: the vertical bar and the Dynamic Island sit on one side, and which side depends on the device posture and on which half of Split View your app lives in. The classic width - insets.left * 2 now computes the wrong number:
// ❌ assumes symmetry
let width = view.bounds.width - view.safeAreaInsets.left * 2
// ✅ every edge on its own
let width = view.bounds.inset(by: view.safeAreaInsets).width// Objective-C
CGRect contentFrame = UIEdgeInsetsInsetRect(self.view.bounds,
self.view.safeAreaInsets);Hardcoded widths. Device-width-to-layout tables, breakpoints like width > 390 — all of it falls apart on a device whose width changes with a movement of the user's hand.
Vertical bars: free, but only for system containers#
Both Duo displays are wider and shorter than a regular iPhone, so system controls move to the side edge: the status bar, the Dynamic Island (now vertical), toolbars and tab bars. Your app gets this automatically — under two conditions: built against the iOS 27.1 SDK, and using system bar containers.
Custom UIToolbar, UINavigationBar and UITabBar instances added to the view hierarchy by hand take no part in the vertical layout at all. Only UINavigationController, UITabBarController and SwiftUI's .toolbar do. If you have a hand-rolled button panel, it's the first candidate for migration.
The most useful part of the new API:
// SwiftUI: pin the primary action, send the secondary ones to overflow
.toolbar {
ToolbarItem(placement: .topBarPinnedTrailing) {
Button("Post", action: post)
}
ToolbarItem(placement: .cancellationAction) {
Button("Close", action: close)
}
}// Objective-C: same semantics via UINavigationItem
self.navigationItem.pinnedTrailingGroup =
[UIBarButtonItemGroup fixedGroupWithRepresentativeItem:nil
items:@[postButton]];
// Secondary actions go to the vertical bar's overflow menu
self.navigationItem.additionalOverflowItems =
[UIDeferredMenuElement elementWithProvider:^(void (^completion)(NSArray *)) {
completion(@[shareAction, archiveAction]);
}];The vertical bar has a fixed width, so Apple explicitly recommends symbol-only buttons: text labels and segmented controls don't fit — keep those in the navigation bar. You can opt a specific screen out of the vertical layout (.toolbarVerticalBehavior(.disabled) in SwiftUI, preferredVerticalBarBehavior in UIKit), but that's a deliberate decision, not the default.
Split View and multiple windows — now on iPhone#
The Duo is the first iPhone with Split View: two apps side by side, 50/50, and every app participates, no opt-in of any kind. Your app can find itself in half a screen at any moment — one more reason fixed widths no longer work.
The second novelty is multiple scenes of a single app, also a first on iPhone. If you already support multi-window on iPad (UIApplicationSupportsMultipleScenes in Info.plist, scenes instead of an AppDelegate-centric lifecycle), most of the work is done. There are no Duo-specific Info.plist keys.
There is behavior iPad never had, though: new windows are created only on the inner display. On a closed device the scene request will fail, and you have to handle that:
// Objective-C: a scene request can now fail
UISceneSessionActivationRequest *request =
[UISceneSessionActivationRequest requestWithRole:UIWindowSceneSessionRoleApplication];
[UIApplication.sharedApplication activateSceneSessionForRequest:request
errorHandler:^(NSError *error) {
// Device is closed — new windows are unavailable
[self showSingleWindowFallback];
}];In SwiftUI, Apple recommends the standard UIWindowSceneActivation affordance: it hides itself when window creation is unavailable and spares you from handling half the cases by hand.
My checklist#
So this doesn't stay theoretical, here's what I'll be doing with my own apps (MeteoHealth first) once Xcode 27.1 lands:
- Rebuild against the iOS 27.1 SDK and open the Duo simulator: Device Hub in Xcode 27.1 can open, close, and fold the virtual device. Posture-dependent bugs don't show up by reading code.
- Grep for assumptions:
UIScreen.main, orientation and idiom branches, symmetric insets, hardcoded widths. - Check the bars: I'm on SwiftUI with system containers, so the vertical layout should come for free — but button order and overflow priorities still need to be looked at with actual eyes.
- Run both Split View scenarios (app on the left and on the right) and both halves.
The honest takeaway from all six talks: if an app already resizes freely — uses size classes, respects safe areas edge by edge, lives in system containers — the iPhone Duo changes almost nothing for it. All the pain goes to apps with baked-in assumptions. Their time runs out October 23.
In the next article of the series I'll dig into the hinge APIs — onHingeChange and UIHingeInteraction — and why Apple forbids building layout from the fold angle.



