Sitemap
Press enter or click to view image in full size
Wireframe designs of a paywall on four different screens: iPhone, iPad Pro, and outer and inner screens of iPhone Duo
10 min readOct 2, 2026

--

Design challenges are among my favorite, so when iPhone Duo was announced by Apple, I was eager to get my hands on the SDK and get tinkering. It wasn’t until nine days later that Apple finally released Xcode 27.1 beta, the software capable of building for iPhone Duo. Since then, I haven’t seen many people talking about designing for iPhone Duo.

My hypothesis is that this is because many developers are seeing that iPhone Duo doesn’t functionally break their app. When I pulled up both of my two projects on iPhone Duo, everything worked. App navigation was still functional on both the inner and outer screens of the device, and nothing was clipped or squished badly enough that it would fail Apple’s review process.

Being functional doesn’t mean that there weren’t issues. I had a brief feeling of lamentation, realizing that the “many screen sizes and form factors” trap was one I had escaped when I left Android development — but here it was, staring me in the face again.

This time is different, though. Developing for both iPhone and iPad sets a good foundation for responsive design — you just have to walk through and check your assumptions, because the new form factor is going to break those, not your app’s functionality.

Before We Get Started

I’ll keep this brief — but there are a couple things I want to mention specifically about working with iPhone Duo.

Obviously, you’ll need Xcode 27.1 beta from Apple’s website. What was less obvious was the fact that a cold boot of Xcode 27.1 beta (which doesn’t have “Beta” on the icon this time, I guess) yields no iPhone Duo device profile and no iOS 27.1 target. Turns out, installing the components when you boot up the beta doesn’t include everything, so once you install the .app file alongside your existing Xcode, you need to explicitly run a command to download the new platform SDK:

# Assuming your beta app filename is "Xcode Beta.app"...
❱❱❱ DEVELOPER_DIR='/Applications/Xcode Beta.app' xcodebuild -downloadPlatform iOS
Finding content...
Automatically resolved architecture variant for platform iOS as 'arm64'.
iOS is already downloaded.
Downloading iOS 27.1 Simulator (24A94401) (arm64): Done.
iOS 27.1 (24A94401) - D5DC52D3-DBC7-4451-963D-ECE860A66036
iOS 27.0 (24A434) - 631174DC-7203-4042-9D12-353C61C0D2B5

Note: There may be a way to do this via UI as well, based on this MacRumors comment. However, I have not tested this.

Beyond the basic install, one useful reference point is to understand iPhone Duo’s size classes. If you’re not familiar with size classes, they are a way of determining whether the width or height of a device is considered compact or regular. An iPhone 18 in portrait mode, for example, is horizontally compact but vertically regular, while an iPad Pro is regular in both dimensions. For iPhone Duo:

  • Outer screen, landscape: .regular horizontally, .compact vertically
  • Outer screen, portrait: .compact horizontally, .regular vertically
  • Inner screen, either orientation: .regular horizontally, .regular vertically

If you’re looking for more depth on size classes, I went into more detail in my article about navigation layouts and Apple also has a great WWDC talk about size classes. But there’s more to responsive design than just this.

Audit First, Then Fix

When building a new feature for multiple displays, you can build from the ground up for the devices you’re targeting. When you’re already feature-complete, however, the process is different — you’re looking for the holes in the design you already have and patching them. A common mistake here is jumping on these bugs like a game of whack-a-mole, but it’s better to first do an audit of the scenario — and we’ll see why.

Let’s take the paywall of my new project, for example, which I’d just completed before the iPhone event. I started by taking a comprehensive inventory of each of iPhone Duo’s six possible states, defined by whether the device is landscape left, landscape right, or portrait, combined with whether the device is folded or unfolded:

Press enter or click to view image in full size
Six screenshots of a paywall, representing each possible display shape of iPhone Duo
Each of the six device form factors, all laid out and easy to analyze.

If you want a quick exercise, take a quick pause here and analyze where you see gaps in the UI compared to what you’d expect. I’ll throw a hint in — there are actually three plans: Monthly, Annual, and Lifetime.

Personally, here’s what stood out:

  1. The hole punch in Closed, Landscape R overlaps the title text. (It seems like this circle can unexpectedly overlap the safe area, at least at this beta stage.)
  2. The plans list in Closed, Landscape modes is completely absent.
  3. The plans lists in all other modes are missing the “Lifetime” option (it’s there, but has to be scrolled to).
  4. The padding on the bottom of the “floating” sheet in the Open modes is absent.
  5. There is a ton of unwanted whitespace in every mode except for Closed, Portrait.
  6. The purchase button in the Closed, Landscape modes is too wide.

This led to a decision: using the paywall as-is on iPhone Duo is not a sufficiently good user experience. While things like unwanted whitespace may be forgivable, at least in the short term, being unable to visualize all plans is a non-starter. If a user wants a one-time purchase but they have to look below the fold to find it, the likelihood is high that they never will.

What I did with this was expand that microcosm (plans not being visible) to the entire design. I took a screenshot of my UI, and used colored boxes to split each element of the design into one of three categories — necessary (pink), nice-to-have (yellow), and unnecessary (teal):

Screenshot of the outer iPhone Duo screen in portrait, showing the paywall, with boxes around different elements to indicate their importance
A quick-and-easy guide to knowing what you need to keep and what can fill the space you have left afterward.

Having this information at hand would help inform decision-making later on — but first, I needed to walk through the assumptions that broke, that got us here to begin with.

You Know What They Say When You Assume

The first assumption: “Size classes represent the device.”

Get Eric Kumlin’s stories in your inbox

Join Medium for free to get updates from this writer.

It seemed obvious. Size classes are one of the proper ways to size content for different displays in SwiftUI. However, they are actually environment values which can be overridden using .environment() and, more specifically, are defined by the system for certain containers such as .sheet(). It turns out, when you are using the inner display of iPhone Duo, the paywall reports that the horizontal dimension is .compact, which contradicts our table above—because this represents the size of the sheet itself.

With my background in web design, these reminded me of container queries (as opposed to media queries). While they carry different levels of precision, the thought process of “based on what?” is the same.

The takeaway: Things like size classes are buckets, rather than precise values, and may not always be what you expect.

The second assumption: “ScrollView == enough room to grow."

A display as tall as a portrait iPad Pro 13" can be shrunk vertically if you switch to landscape without losing much. You can probably even shrink it down to an iPad Air and be fine. But that assumption likely doesn’t hold on an iPhone in landscape mode. At some point, your ScrollView may simply not have enough vertical room to show enough content to be useful.

Specifically for iPhone 18 in landscape mode, I chose a two-column layout for the paywall — but because of how design had been made responsive with size classes, this layout wasn’t applying on the taller iPhone Duo display.

The takeaway: There’s always an underlying assumption of aspect ratio, and that has to be considered with every design.

The third assumption: “Hardware will never get in the way.”

This one is tricky because it’s the easiest one to think you’ve accounted for, but then be thrown a curveball.

As an example, iPhones shipped for over a decade with a perfectly rectangular screen. iPhone X brought the “notch”, allowing Apple to expand the screen edge-to-edge, and iPhone 14 Pro later replaced this design with pill-shaped cut-out. In hindsight, this seems like a logical evolution — and it has been minimally invasive — so it’s easy to think we’ve accounted for it. But then Apple decides to put a hole punch in the corner of the screen, and everything goes out the window.

The takeaway: Never assume that you know where hardware is or isn’t.

With assumptions checked, it was time to make something of them.

Moulding Decisions from the Abstract

The first decision I weighed was making the ScrollView taller, but I rejected this proposal for two reasons. First, if you look back at the necessary and unnecessary component diagram, you can see that there is a "necessary" item for the entire verticality of the screen, minus the little caption at the top. On top of this, we saw that the landscape form factor had so little available space that it showed no plans. There was simply no way to recoup enough vertical real estate. Second, forcing people to scroll on a screen like this is a last resort. It was originally added just in case someone had a little bit less screen height, but it was never intended to compensate for having this little of it.

Instead, I made the decision to first trim out everything I could. This meant reducing the feature rows down as much as I could, removing the little “icons” on each of the plans when space simply didn’t exist for them, and tightening up the whitespace where I’d marked it as “unnecessary” earlier — without violating the Human Interface Guidelines.

The biggest win, however, came in the decision to reflow the layout into a grid when space is too tight. In fact, one of my original designs had used a horizontal layout for the plans, so I decided to bring this back in the event that there was not enough vertical space to accommodate all of them. For a visual aid, this is what changed:

Press enter or click to view image in full size
Diagram showing two layouts for a list of three paywall plans; the first has them as rectangles in three rows, the second as squares in three columns
Does it take up more room horizontally? Yes. And that’s the point.

This is very easily achieved with Apple’s own ViewThatFits; I can effectively just throw both views at SwiftUI and it will pick the first one that fits the space:

ViewThatFits {
let isVerticallyConstrained = verticalSizeClass == .compact

planList(axis: .horizontal, displayMode: .cell)
planList(axis: .vertical, displayMode: isVerticallyConstrained ? .compactRow : .row)
}

Mind you, these changes didn’t fix everything — just the big rocks. I addressed the hole punch overlapping the safe area by forcing a .toolbar(); fixed the sheet's bottom padding with a bit of a hack using .ignoresSafeArea(edges: [.bottom]), plus some manual padding; and the button width was much improved with the two-column layout I settled on for landscape viewing.

Finally, I had layouts I was very happy with. At least, on iPhone Duo.

When a Fix Becomes a Regression

Don’t forget: the regular iPhone still exists, and boy am I glad I tested it before shipping these changes. The clever tricks I’d used to achieve the updated design — involving size classes, ViewThatFits, and more—broke something on iPhone 18 in landscape mode. In my attempt to reduce the "FREE, ALWAYS" copy, I'd moved it into the footer of the "PRO ONLY" card, but in some orientations, the copy was forced onto a single, truncated line of text. I noticed other issues had leaked in as well, like having too much spacing under "CHOOSE A PLAN" and around the "Restore Purchases" button row.

Press enter or click to view image in full size

These are all fairly trivial to fix, but they highlight the importance of checking your work — just because you don’t expect something to break doesn’t mean it didn’t. When you make form factor changes, they are relevant to every device you’re shipping to, not just the new one.

But with those fixes, and a few other changes to tighten up some copy here and there, I ended up with a much better paywall across the full matrix of iPhone Duo screen shapes and sizes — without regressions to the existing iPhone 18 paywall experience:

Press enter or click to view image in full size
Six screenshots of the same paywall after all changes, representing the updated experience with each possible display shape of iPhone Duo
A much better experience in all dimensions. Plans are visible, layouts don’t feel cramped or clustered, and nothing needs to scroll.

Where We Go from Here

As iPhone Duo hasn’t shipped yet, it’s possible that the hardware won’t work exactly as the Simulator does — or, iOS 27.1 at public release may be different than the beta SDK we see today. Aside from that, these form factor changes may affect any surface in your app. (Though, probably not all of them — funnily enough, the paywall I designed for API Canvas needed almost no work to adjust for iPhone Duo.) So, being finished with my paywall conversion now, I’ll be moving on to other app surfaces, reusing the same sequence: audit → list assumptions → propose decisions → accept or reject decisions → verify the full matrix.

iPhone Duo will not be the last form factor. There remain rumors of a screen-based “HomePad” and a clamshell-style iPhone, suggesting that the form factor fragmentation I’d hoped to leave behind with Android is still here, just in a different shape. What this process has illustrated is that SwiftUI has the tools to handle this, as long as our focus is on building for the space we have, rather than the device we’re on.

This article was originally published on erickumlin.com.

--

--

Eric Kumlin
Eric Kumlin

Staff Engineer • Shipping API Canvas for iOS • Writing about Swift/native dev at erickumlin.com • 10+ years full-stack → mobile • Building in public