So…I am hitting a wall here and could use some guidance towards best practice.
I’ve developed an app in Xcode/SwiftUI that renders just fine on the iPhone - text, images, buttons, frames…everything is nicely centered on the screen or scrolls where and when I want.
The iPad though…not so much. I’m having issues with tops and bottoms being cut off in scrollviews. These are just straight up text screens too - the ones with other elements/controls…they’re rendering fine.
I’ve tried a mix of geometry, vstack, scrollview, padding, spacers…the lot of it. Nothing I seem to do works - the views do not want to fill and fit properly.
And, of course, the issue becomes worse the moment you flip the iPad into landscape view. Or use the 13” models.
I’d imagine others are battling these issues as well and found solutions, so I decided to hit up the brain trust.
All my apps work on both the iPhone and iPad, but due to the amount of changes - some structural - that are required to get an iPhone version to look and work properly on the iPad, I use two different views:
@main
struct MainApp: App {
// ...
var body: some Scene {
WindowGroup {
if(UIDevice.current.userInterfaceIdiom == .pad) {
TabletView()
} else {
PhoneView()
}
}
}
}
So, if the user is using an iPhone, the PhoneView()
is the main entry point. For iPads, it's TabletView()
.
The reason I did this is because the iPad has much more space and allows me to do more things, so the TabletView
has more things in it.
Also, I'd rather not have one big, unmanageable View
full of if ... else
statements and ternary operators.
It also means your spacers and padding values apply only to that device type.
Where the two views have similar UI, those bits are extracted into their own little View
structs and called within those two main entry points.
When you separate out the two views you may find you're duplicating some work, but you'll also be working on a view that only applies to an iPad or an iPhone and not both. You can make a change in the TabletView
and be assured it hasn't affected the PhoneView
, so you haven't got to retest that change on the iPhone.
You can also then expand this to include Vision Pro, Apple TV, and any other device idioms Apple has or releases in future, and you won't need to add more and more if ... else
and ternary operators in that one massive file.
If you're having issues with specific models of an iPad or iPhone I'd say you're maybe using too many magic numbers in your code? You've probably found that the padding on an iPhone 13 mini for some label is 5, while on an iPhone 14 Plus it's 12 so you've written that in. You should rework this to align things naturally using SwiftUI's HStack
s, YStack
s etc.
Or, have a consistent padding for your UI so that it looks the same on every device. Let's say you can fit 8 text fields vertically in a form on an iPhone 12 mini, and 10 on an iPhone 15 Pro, that's fine. You don't need to space everything out to always fit 8 fields on the screen, so the padding between the fields can be the same on every device.
If you want to show us an example of what's causing you issues, drop some code here (properly-formatted using the code formatting toolbar) and screenshots showing us the issue in the UI so we can visualise it.