iPhone App Development
Screen Resolution Detection
iOS Programming
Mobile App Design
Device Compatibility

in iPhone App How to detect the screen resolution of the device

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

Introduction

In iPhone development, you rarely need the exact physical resolution for normal layout decisions. iOS layout is designed around points, size classes, and safe areas, but if you do need resolution information for rendering, camera, or diagnostics, UIScreen gives you both logical size and native pixel size.

Know the Difference Between Points and Pixels

A lot of confusion comes from mixing up three related values:

  • bounds in points, used by UIKit layout
  • scale, which tells you how many pixels represent one point
  • native bounds in pixels, which reports the device's actual pixel resolution

For most app UI, points matter more than pixels. If your view layout is based on device-specific pixel counts, the design usually becomes brittle very quickly.

Read Screen Information with UIScreen

In UIKit, the simplest way to inspect the main display is through UIScreen.main.

swift
1import UIKit
2
3let screen = UIScreen.main
4let sizeInPoints = screen.bounds.size
5let scale = screen.scale
6let nativeSize = screen.nativeBounds.size
7let nativeScale = screen.nativeScale
8
9print("points: \(sizeInPoints.width)x\(sizeInPoints.height)")
10print("scale: \(scale)")
11print("pixels: \(nativeSize.width)x\(nativeSize.height)")
12print("native scale: \(nativeScale)")

This gives you enough information to distinguish logical layout size from physical pixel density. scale is usually what you care about for asset rendering, while nativeBounds is useful when you need the hardware pixel grid.

Use Traits for Layout Decisions

If the real question is "how should my UI adapt", resolution is often the wrong signal. Trait collections and safe areas are the more stable abstraction.

swift
1override func viewDidLoad() {
2    super.viewDidLoad()
3
4    let horizontal = traitCollection.horizontalSizeClass
5    let vertical = traitCollection.verticalSizeClass
6    print("horizontal size class: \(horizontal.rawValue)")
7    print("vertical size class: \(vertical.rawValue)")
8}

This survives new device releases much better than checking for one hard-coded resolution. A screen with a different pixel count can still belong to the same practical layout category.

Avoid Device Tables When Possible

A common beginner pattern is creating a long switch statement of known device resolutions. That works until Apple ships a new device or display mode and your code immediately becomes stale.

Instead of doing this:

swift
if UIScreen.main.nativeBounds.height == 2556 {
    print("specific iPhone model")
}

prefer asking what capability you actually need:

  • compact or regular width
  • retina scale factor
  • safe area insets
  • available width after rotation

That makes the code resilient to future hardware.

Example: Choose an Image Variant at Runtime

If you truly need pixel-density-aware behavior, use scale rather than absolute resolution checks.

swift
1func imageNameForCurrentScreen() -> String {
2    switch UIScreen.main.scale {
3    case 3.0:
4        return "hero@3x"
5    case 2.0:
6        return "hero@2x"
7    default:
8        return "hero"
9    }
10}

In practice, asset catalogs handle this automatically, so manual branching is only necessary for custom rendering logic or debugging.

SwiftUI Still Uses the Same Underlying Concepts

SwiftUI encourages adaptive layout even more strongly than UIKit, but the screen APIs are still available when required. For example, you can inspect UIScreen.main.bounds for diagnostics, though layout should usually be driven by container geometry and environment values.

swift
1import SwiftUI
2
3struct DiagnosticsView: View {
4    var body: some View {
5        Text("Pixels: \(Int(UIScreen.main.nativeBounds.width)) x \(Int(UIScreen.main.nativeBounds.height))")
6    }
7}

This is fine for a debug screen. It is not a great basis for core layout logic.

Common Pitfalls

The most common mistake is designing views against pixel resolution instead of points and Auto Layout. That usually breaks across rotation, Dynamic Type, and future devices.

Another mistake is assuming bounds is the same as physical pixels. bounds is in points. If you need actual resolution, use nativeBounds.

Developers also sometimes use resolution to infer device model. That is fragile because display zoom modes, simulator settings, and future devices can share or alter those numbers.

Finally, do not forget safe area insets. Even if two phones have similar point sizes, the usable layout area can differ because of the notch or home indicator.

Summary

  • Use UIScreen.main.bounds for logical size in points.
  • Use UIScreen.main.scale and nativeBounds only when pixel-level information is truly needed.
  • Prefer traits, safe areas, and Auto Layout for adaptive UI.
  • Avoid hard-coded device-resolution tables unless you have a very specific hardware need.
  • Treat resolution as a diagnostic signal, not as the main driver of app layout.

Related reading
Free course
Beginner
7 lessons
2 hours
Tackling System Design Interview Problems

A short course that equips you with the skills to approach system design interviews methodically.

Start the free course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions