DEV Community

sfrrvsdbbf
sfrrvsdbbf

Posted on • Edited on

2 Tips to improve "unfriendly" iPad apps 【SwiftUI】

iPhone apps can run as iPad apps simply by adding iPad as a build target. However, without some optimization for the iPad, the app can be very user-unfriendly. Unfortunately, such iPad apps are not uncommon in the App Store.

In this article, I will introduce two minimal techniques to make "unfriendly" iPad apps decent with just a few adjustments.

Bad example

Target

  • Primarily an iPhone app
  • Limited resources for iPad compatibility
  • Uses common UI patterns (bottom tabs, stack navigation, lists, etc.)
struct ContentView: View {
    var body: some View {
        TabView {
            NavigationStack {
                List {
                     /* … */
                }
                .navigationTitle("Home")
                .toolbar {
                    EditButton()
                    ShareLink(item: .init())
                }
            }
            .tabItem { Label("Home", systemImage: "house") }
            /* … */
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

Tip 1: Support Landscape Orientation

Many iPhone apps only support portrait orientation, and many iPad apps follow suit. iPad users generally use their devices in landscape orientation, and it can be frustrating to use apps that only support portrait mode. Unless there is a special reason, you should support landscape orientation.

LandScape

Tip 2: Avoiding Unnecessary Horizontal Stretching of Content

A typical issue when adapting an iPhone app for the iPad in landscape orientation is that the content stretches too much horizontally, which looks unnatural. Ideally, you would redesign the app's UI specifically for the iPad, but that requires significant resources. Here, we introduce the approach of adding margins to the left and right sides of the content, which is commonly used in many apps.

AddSpace

struct AddSpace: ViewModifier {
    func body(content: Content) -> some View {
        GeometryReader {
            content
                .safeAreaPadding(.horizontal,
                                 $0.size.width > 1100 ? 200 : 0)
        }
    }
}
//===================================
struct ContentView: View {
    var body: some View {
        TabView {
            NavigationStack {
                List { 
                    /* … */
                }
                .modifier(AddSpace())
                /* … */
            }
            /* … */
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

For Lists and ScrollViews, just adding padding on the sides can disrupt the appearance and gesture recognition area. We adjusted the left and right safe areas to add margins, allowing us to maintain a usable design without changing the iPhone app's layout.

Challenge of Split View

A typical design for landscape-oriented iPad apps includes using a sidebar for a Split View. If you simply replace a bottom tab with a sidebar for a selection-based Split View, it seems feasible to achieve a good result without allocating additional resources.

Split View

struct ContentView: View {
    @State private var selection: String? = Home
    var body: some View {
        NavigationSplitView {
            List(selection: self.$selection) {
                Label("Home", systemImage: house).tag("Home")
                Label("Favorite", systemImage: star).tag("Favorite")
                Label("Setting", systemImage: "gearshape").tag("Setting")
                Label("Help", systemImage: "info").tag("Help")
            }
        } detail: {
            switch self.selection {
                case "Home": /* … */
                case "Favorite": /* … */
                case "Setting": /* … */
                case "Help": /* … */
                default: /* … */
            }
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

When you actually try this, it will require dedicating resources in various ways. For example:

  • Considering different scenarios, such as when the window width is narrow
  • Testing the behavior differences of content view instances when switching tabs (they don’t disappear with bottom tabs but disappear with Split View)
  • Testing the operation of the navigation stack in the detail panel (toolbars and navigation links often behave unexpectedly)
  • Starting unnecessary implementations like "adding sidebar items" or "automatic switching between bottom tabs and sidebar" due to getting carried away

If you have no experience with implementing Split View, I do not recommend diving into it casually.

Note 1: Disable Multiple Windows

Unlike iPhones, iPads can have multiple windows. To avoid issues from unexpected user inputs, disable multiple windows by setting "Enable Multiple Windows" to NO in Info.plist.

Enable Multiple Windows

Note 2: Implementing iPad-Specific Code

You should use UIDevice.current.userInterfaceIdiom.

struct ContentView: View {
    var body: some View {
        switch UIDevice.current.userInterfaceIdiom {
            case .phone: Text(I am iPhone")
            case .pad: Text(“I am iPad")
            default: EmptyView()
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

Top comments (0)