25

I'd like to display different views when building for iOS and iPadOS. Currently, I know I can do

import SwiftUI

struct ContentView: View {
    #if targetEnvironment(macCatalyst)
    var body: some View {
        Text("Hello")
    }
    #else
    var body: some View {
        Text("Hello")
    }
    #endif
}

to display different views between macOS and iPadOS/iOS (introduced in Swift 4/5). But how do I differentiate between the latter? I can't seem to use targetEnvironment...

cyril
  • 3,020
  • 6
  • 36
  • 61

3 Answers3

26

I use this in my code:

    private var idiom : UIUserInterfaceIdiom { UIDevice.current.userInterfaceIdiom }
    private var isPortrait : Bool { UIDevice.current.orientation.isPortrait }

Then you can do this:

    var body: some View {
        NavigationView {
            masterView()

            if isPortrait {
                portraitDetailView()
            } else {
                landscapeDetailView()
            }
        }
    }

    private func portraitDetailView() -> some View {
        if idiom == .pad {
            return Text("iPadOS")
        } else {
            return Text("iOS")
        }
    }
caram
  • 1,494
  • 13
  • 21
17

I add the following code as an extension of UIDevice.

extension UIDevice {
    static var isIPad: Bool {
        UIDevice.current.userInterfaceIdiom == .pad
    }
    
    static var isIPhone: Bool {
        UIDevice.current.userInterfaceIdiom == .phone
    }
}

Now anywhere I can call UIDevice.isIPad or UIDevice.isIPhone to know which device is it.

Mahmud Ahsan
  • 1,755
  • 19
  • 18
  • I prefer this solution but I believe it should be used as UIDevice.current.isIpad and UIDevice.current.isIphone. At least that's how I had to write it to work. – johnnelm9r Mar 21 '22 at 04:22
7

To return different view types you can use AnyView eraser type:

if UIDevice.current.userInterfaceIdiom == .pad {
    return AnyView(Text("Hello, World!"))
} else {
    return AnyView(Rectangle().background(Color.green))
}
Zontag
  • 147
  • 2
  • 7