545

How can one get the dimensions of the screen in iOS?

Currently, I use:

lCurrentWidth = self.view.frame.size.width;
lCurrentHeight = self.view.frame.size.height;

in viewWillAppear: and willAnimateRotationToInterfaceOrientation:duration:

The first time I get the entire screen size. The second time i get the screen minus the nav bar.

Caleb
  • 124,013
  • 19
  • 183
  • 272
griotspeak
  • 13,022
  • 13
  • 43
  • 54
  • Ensure that your app is actually full screen and you are not [seeing black bars around it -- this may be your solution if you are](https://stackoverflow.com/a/43835717/111307) – bobobobo Dec 25 '20 at 21:59

18 Answers18

1106

How can one get the dimensions of the screen in iOS?

The problem with the code that you posted is that you're counting on the view size to match that of the screen, and as you've seen that's not always the case. If you need the screen size, you should look at the object that represents the screen itself, like this:

CGRect screenRect = [[UIScreen mainScreen] bounds];
CGFloat screenWidth = screenRect.size.width;
CGFloat screenHeight = screenRect.size.height;

Update for split view: In comments, Dmitry asked:

How can I get the size of the screen in the split view?

The code given above reports the size of the screen, even in split screen mode. When you use split screen mode, your app's window changes. If the code above doesn't give you the information you expect, then like the OP, you're looking at the wrong object. In this case, though, you should look at the window instead of the screen, like this:

CGRect windowRect = self.view.window.frame;
CGFloat windowWidth = windowRect.size.width;
CGFloat windowHeight = windowRect.size.height;

Swift 4.2

let screenRect = UIScreen.main.bounds
let screenWidth = screenRect.size.width
let screenHeight = screenRect.size.height

// split screen            
let windowRect = self.view.window?.frame
let windowWidth = windowRect?.size.width
let windowHeight = windowRect?.size.height
Caleb
  • 124,013
  • 19
  • 183
  • 272
  • should i just use interface rotation to figure out which is actually 'width' or height. – griotspeak Apr 15 '11 at 15:14
  • 7
    Orientation is really managed at the view controller level. Take a look at [Managing a View Controller's Interface Orientation](http://tinyurl.com/6yso8zt). So yes, look at your view controller's interfaceOrientation property. BTW, you asked about the screen size, so that's what I showed you, but for displaying your content you should probably use the window's bounds or the screen's applicationFrame, depending on what you're doing. – Caleb Apr 15 '11 at 15:25
  • 1
    Thank you. I couldn't work those methods out before, but i will try again. – griotspeak Apr 15 '11 at 15:31
  • turns out that my previous issue was not subtracting the height of the navigation bar. – griotspeak Apr 15 '11 at 16:15
  • 2
    it's useful to note that this returns the *full* screen width without padding. Simply subtract your app's padding (usually 20 on each side) from these results to get the 'usable' space for most elements – Nick Daugherty Aug 30 '12 at 16:25
  • 2
    @NickDaugherty Yes, that's the point -- the OP wanted the screen dimensions. Where you put objects on the screen is entirely up to you and depends on what type of app you're building. If you're displaying a photo or a game interface, for example, you might not want any padding at all. – Caleb Aug 30 '12 at 16:29
  • @Caleb Yep absolutely, just pointing out the difference for future searchers. – Nick Daugherty Aug 30 '12 at 20:10
  • 5
    Note however that this returns a value measured in points. So if you were expecting the screen resolution in pixels, the result would be incorrect, and you should multiply the result by `[UIScreen scale]`. – Robotbugs Aug 20 '13 at 01:48
  • @Robotbugs That's a good point, but since questions considers frame size, a result in points seems to be what the OP is looking for. (And it should be -- drawing, sizing, etc. are done in points, not pixels.) – Caleb Aug 20 '13 at 01:58
  • 3
    Someone pointed out that since [a CGRect can have negative width or height](http://bit.ly/1yu5lDs), we should use `CGRectGetWidth()` and `CGRectGetHeight()` instead of directly accessing the `size` field in the rectangle. I don't think it's ever likely to be a problem with respect to the screen rectangle, but I suppose it's something to be aware of. – Caleb Sep 26 '14 at 14:16
  • 1
    Accessing the height and width directly is not recommended. The documentation states that you should use CGRectGetWidth(CGRect) and CGRectGetHeight(CGRect). – Vinny Rose Sep 26 '14 at 16:53
  • 1
    @VinnyRose And the documentation also tells us *why* those are recommended, i.e. to normalize the width and height so that you don't get negative values. As I explained previously, I don't believe there's much danger of that with the screen rectangle, but I pointed the issue out anyway for completeness. – Caleb Sep 26 '14 at 17:05
  • 1
    @Caleb Ah, I didn't see that comment. Yes there is no danger, I agree, but that is not the point. It is a matter of code style in this case. And as this is a top hit on search engines it is likely that new programmers will see this and think it is the correct way to access these value in all situations. Perhaps your comment is enough, hopefully it's up-voted by many, but I would rather have it in the answer. – Vinny Rose Sep 26 '14 at 17:32
  • For anyone looking here post-iOS 9; apple devs at WWDC specifically called out not using any geometry from "screen" anymore, since multitasking means that you care more about your window than your screen. – TahoeWolverine Oct 29 '15 at 21:40
  • It doesn't work correctly in the split view. How can I get the size of the screen in the split view? – Dmitry Feb 13 '16 at 16:08
  • 1
    @Dmitry I added an update to cover split screen. In short, the code works exactly as it always has, but you're probably looking for the window size instead of the screen size. Code provided for that above. – Caleb Feb 13 '16 at 17:22
63

Careful, [UIScreen mainScreen] contains status bar as well, if you want to retrieve the frame for your application (excluding status bar) you should use

+ (CGFloat) window_height   {
    return [UIScreen mainScreen].applicationFrame.size.height;
}

+ (CGFloat) window_width   {
    return [UIScreen mainScreen].applicationFrame.size.width;
}
Ege Akpinar
  • 3,266
  • 1
  • 23
  • 29
48

I've translated some of the above Objective-C answers into Swift code. Each translation is proceeded with a reference to the original answer.

Main Answer

let screen = UIScreen.main.bounds
let screenWidth = screen.size.width
let screenHeight = screen.size.height

##Simple Function Answer

func windowHeight() -> CGFloat {
    return UIScreen.main.bounds.size.height
}

func windowWidth() -> CGFloat {
    return UIScreen.main.bounds.size.width
}

##Device Orientation Answer

let screenHeight: CGFloat
let statusBarOrientation = UIApplication.shared.statusBarOrientation
// it is important to do this after presentModalViewController:animated:
if (statusBarOrientation != .portrait
    && statusBarOrientation != .portraitUpsideDown) {
    screenHeight = UIScreen.main.bounds.size.width
} else {
    screenHeight = UIScreen.main.bounds.size.height
}

##Log Answer

let screenWidth = UIScreen.main.bounds.size.width
let screenHeight = UIScreen.main.bounds.size.height
println("width: \(screenWidth)")
println("height: \(screenHeight)")
Michal Šrůtek
  • 1,647
  • 16
  • 17
Martin Woolstenhulme
  • 3,968
  • 4
  • 24
  • 25
  • Seems like there's a typo in the Log Answer: Should it be UIScreen.mainScreen().bounds.size.width? I get a compile error without the ".bounds". – stone Apr 29 '15 at 06:54
  • @skypecakes I've fixed the answer to include ".bounds". Thanks for the feedback. – Martin Woolstenhulme Apr 29 '15 at 15:57
  • applicationFrame is deprecated in iOS 9 and above, replace with `return UIScreen.mainScreen().bounds].size.width` – Suhaib Sep 07 '16 at 03:31
39

I have used these convenience methods before:

- (CGRect)getScreenFrameForCurrentOrientation {
    return [self getScreenFrameForOrientation:[UIApplication sharedApplication].statusBarOrientation];
}

- (CGRect)getScreenFrameForOrientation:(UIInterfaceOrientation)orientation {

    CGRect fullScreenRect = [[UIScreen mainScreen] bounds];

    // implicitly in Portrait orientation.
    if (UIInterfaceOrientationIsLandscape(orientation)) {
      CGRect temp = CGRectZero;
      temp.size.width = fullScreenRect.size.height;
      temp.size.height = fullScreenRect.size.width;
      fullScreenRect = temp;
    }

    if (![[UIApplication sharedApplication] statusBarHidden]) {
      CGFloat statusBarHeight = 20; // Needs a better solution, FYI statusBarFrame reports wrong in some cases..
      fullScreenRect.size.height -= statusBarHeight;
    }

    return fullScreenRect;
} 
quaertym
  • 3,917
  • 2
  • 29
  • 41
Luke Mcneice
  • 3,012
  • 4
  • 38
  • 50
  • Nice solution, but be careful that temp seems to have undefined origin. – szemian Jul 22 '12 at 13:17
  • 4
    Do you get 0,0 as default? When I logged the fullScreenRect, it gave me: {{8.03294e-35, 3.09816e-40}, {480, 320}}. I chose to initialized with CGRect temp = CGRectZero; – szemian Jul 22 '12 at 14:40
  • 1
    UIInterfaceOrientationIsLandscape does not handle 'UIDeviceOrientationFaceUp' and 'UIDeviceOrientationFaceDown' which may be returned from UIDevice. – Andriy Aug 13 '12 at 14:53
  • 6
    You may like to use the property screen.applicationFrame instead of screen.bounds which takes care of the status bar. – Geraud.ch Oct 09 '12 at 11:50
  • Turns out in some cases applicationFrame dosn't return frame with a correctly subtracted status bar (full screen modals from a splitview) – Luke Mcneice Jan 13 '13 at 16:32
15

I realize that this is an old post, but sometimes I find it useful to #define constants like these so I do not have to worry about it:

#define DEVICE_SIZE [[[[UIApplication sharedApplication] keyWindow] rootViewController].view convertRect:[[UIScreen mainScreen] bounds] fromView:nil].size

The above constant should return the correct size no matter the device orientation. Then getting the dimensions is as simple as:

lCurrentWidth = DEVICE_SIZE.width;
lCurrentHeight = DEVICE_SIZE.height;
A Random User
  • 183
  • 1
  • 8
13

It's very, very easy to get your device size as well as take into account the orientation:

// grab the window frame and adjust it for orientation
UIView *rootView = [[[UIApplication sharedApplication] keyWindow] 
                                   rootViewController].view;
CGRect originalFrame = [[UIScreen mainScreen] bounds];
CGRect adjustedFrame = [rootView convertRect:originalFrame fromView:nil];
memmons
  • 40,222
  • 21
  • 149
  • 183
  • Hi, I use this in viewDidLoad on an iPad landscape only app, is there any reason why it gets the correct value first time, then the value 'flips' on every load after than, ie it reads it as lanscape first view, then I navigate away and back to the view and it seems to read it as portrait even tho no orientation change was made? Thanks – craigk Apr 11 '13 at 04:14
  • @LukeMcneice In my production code I have an assert to make sure that a frame is found...I have yet to have that assert fail. What is being returned for rootView and originalFrame? – memmons Apr 18 '13 at 15:07
  • I am using this technique in a singleton to get the orientation-corrected width/height. However, if this code runs while a UIAlert window showing the convertRect returns adjustedFrame with a size (width at least) of 0. Any thoughts what is going on with that? – Electro-Bunny Apr 19 '13 at 13:41
  • Ah. An `UIAlertView` will insert itself as the keyWindow's rootViewController view. I have logic that avoids the corner case because if an alert view is up, the user can't interact with the keyboard, so there is typically no need to grab the keyboard frame at that time. – memmons Apr 19 '13 at 16:14
  • Thanks for the insight. I was using your technique in a banner ad singleton. It was a simple and nice way of telling the ad api the size of the screen frame for a new ad. Since I will not be able to mutually exclude banner ads and UIAlert's I will likely fall back to detecting landscape vs. portrait and brute force switching x/y as necessary. – Electro-Bunny Apr 19 '13 at 18:23
10

Make use of these Structs to know useful info about the current device in Swift.

struct ScreenSize { // Answer to OP's question
    
    static let SCREEN_WIDTH         = UIScreen.main.bounds.size.width
    static let SCREEN_HEIGHT        = UIScreen.main.bounds.size.height
    static let SCREEN_MAX_LENGTH    = max(ScreenSize.SCREEN_WIDTH, ScreenSize.SCREEN_HEIGHT)
    static let SCREEN_MIN_LENGTH    = min(ScreenSize.SCREEN_WIDTH, ScreenSize.SCREEN_HEIGHT)
    
}

struct DeviceType { //Use this to check what is the device kind you're working with
    
    static let IS_IPHONE_4_OR_LESS  = UIDevice.current.userInterfaceIdiom == .phone && ScreenSize.SCREEN_MAX_LENGTH < 568.0
    static let IS_IPHONE_SE         = UIDevice.current.userInterfaceIdiom == .phone && ScreenSize.SCREEN_MAX_LENGTH == 568.0
    static let IS_IPHONE_7          = UIDevice.current.userInterfaceIdiom == .phone && ScreenSize.SCREEN_MAX_LENGTH == 667.0
    static let IS_IPHONE_7PLUS      = UIDevice.current.userInterfaceIdiom == .phone && ScreenSize.SCREEN_MAX_LENGTH == 736.0
    static let IS_IPHONE_X          = UIDevice.current.userInterfaceIdiom == .phone && ScreenSize.SCREEN_MAX_LENGTH == 812.0
    static let IS_IPAD              = UIDevice.current.userInterfaceIdiom == .pad && ScreenSize.SCREEN_MAX_LENGTH == 1024.0
    
}


struct iOSVersion { //Get current device's iOS version
    
    static let SYS_VERSION_FLOAT  = (UIDevice.current.systemVersion as NSString).floatValue
    static let iOS7               = (iOSVersion.SYS_VERSION_FLOAT >= 7.0 && iOSVersion.SYS_VERSION_FLOAT < 8.0)
    static let iOS8               = (iOSVersion.SYS_VERSION_FLOAT >= 8.0 && iOSVersion.SYS_VERSION_FLOAT < 9.0)
    static let iOS9               = (iOSVersion.SYS_VERSION_FLOAT >= 9.0 && iOSVersion.SYS_VERSION_FLOAT < 10.0)
    static let iOS10              = (iOSVersion.SYS_VERSION_FLOAT >= 10.0 && iOSVersion.SYS_VERSION_FLOAT < 11.0)
    static let iOS11              = (iOSVersion.SYS_VERSION_FLOAT >= 11.0 && iOSVersion.SYS_VERSION_FLOAT < 12.0)
    static let iOS12              = (iOSVersion.SYS_VERSION_FLOAT >= 12.0 && iOSVersion.SYS_VERSION_FLOAT < 13.0)
    static let iOS13              = (iOSVersion.SYS_VERSION_FLOAT >= 13.0 && iOSVersion.SYS_VERSION_FLOAT < 14.0)
    static let iOS14              = (iOSVersion.SYS_VERSION_FLOAT >= 14.0 && iOSVersion.SYS_VERSION_FLOAT < 15.0)
    static let iOS15              = (iOSVersion.SYS_VERSION_FLOAT >= 15.0 && iOSVersion.SYS_VERSION_FLOAT < 16.0)
    static let iOS16              = (iOSVersion.SYS_VERSION_FLOAT >= 16.0 && iOSVersion.SYS_VERSION_FLOAT < 17.0)
    
}
badhanganesh
  • 3,427
  • 3
  • 18
  • 39
9

We have to consider the orientation of device too:

CGFloat screenHeight;
// it is important to do this after presentModalViewController:animated:
if ([[UIApplication sharedApplication] statusBarOrientation] == UIDeviceOrientationPortrait || [[UIApplication sharedApplication] statusBarOrientation] == UIDeviceOrientationPortraitUpsideDown){
    screenHeight = [UIScreen mainScreen].applicationFrame.size.height;
}
else{
    screenHeight = [UIScreen mainScreen].applicationFrame.size.width;
}
Oleh Kudinov
  • 2,533
  • 28
  • 30
  • Good solution I did this to get my iPad app working in landscape from inside an embedded view controller when presenting a modal VC. – StackRunner Oct 16 '14 at 20:58
8
NSLog(@"%.0f", [[UIScreen mainScreen] bounds].size.width);
NSLog(@"%.0f", [[UIScreen mainScreen] bounds].size.height);
Gaurav Gilani
  • 1,584
  • 14
  • 18
6

Here i have updated for swift 3

applicationFrame deprecated from iOS 9

In swift three they have removed () and they have changed few naming convention, you can refer here Link

func windowHeight() -> CGFloat {
    return UIScreen.main.bounds.size.height
}

func windowWidth() -> CGFloat {
    return UIScreen.main.bounds.size.width
}
karthikeyan
  • 3,821
  • 3
  • 22
  • 45
5

The modern answer:

if your app support split view on iPad, this problem becomes a little complicated. You need window's size, not the screen's, which may contain 2 apps. Window's size may also vary while running.

Use app's main window's size:

UIApplication.shared.delegate?.window??.bounds.size ?? .zero

Note: The method above may get wrong value before window becoming key window when starting up. if you only need width, method below is very recommended:

UIApplication.shared.statusBarFrame.width

The old solution using UIScreen.main.bounds will return the device's bounds. If your app running in split view mode, it get the wrong dimensions.

self.view.window in the hottest answer may get wrong size when app contains 2 or more windows and the window have small size.

leavez
  • 2,119
  • 2
  • 27
  • 36
4

If you want screen width/height regardless of device orientation (good for sizing portrait only view controllers being launched from landscape orientations):

CGFloat screenWidthInPoints = [UIScreen mainScreen].nativeBounds.size.width/[UIScreen mainScreen].nativeScale;
CGFloat screenHeightInPoints = [UIScreen mainScreen].nativeBounds.size.height/[UIScreen mainScreen].nativeScale;

[UIScreen mainScreen].nativeBounds <-- From the docs --> The bounding rectangle of the physical screen, measured in pixels. This rectangle is based on the device in a portrait-up orientation. This value does not change as the device rotates.

John Erck
  • 9,478
  • 8
  • 61
  • 71
3

Here is a Swift way to get screen sizes:

print(screenWidth)
print(screenHeight)

var screenWidth: CGFloat {
    if UIInterfaceOrientationIsPortrait(screenOrientation) {
        return UIScreen.mainScreen().bounds.size.width
    } else {
        return UIScreen.mainScreen().bounds.size.height
    }
}

var screenHeight: CGFloat {
    if UIInterfaceOrientationIsPortrait(screenOrientation) {
        return UIScreen.mainScreen().bounds.size.height
    } else {
        return UIScreen.mainScreen().bounds.size.width
    }
}

var screenOrientation: UIInterfaceOrientation {
    return UIApplication.sharedApplication().statusBarOrientation
}

These are included as a standard function in:

https://github.com/goktugyil/EZSwiftExtensions

Esqarrouth
  • 38,543
  • 21
  • 161
  • 168
3

iOS 13+ answer (source of the code finding the key window):

guard let window = UIApplication.shared.windows.first(where: { $0.isKeyWindow }) else {
    return
}

let windowWidth = window.frame.width
let windowHeight = window.frame.height
Tamás Sengel
  • 55,884
  • 29
  • 169
  • 223
2

swift 3.0

for width

UIScreen.main.bounds.size.width

for height

UIScreen.main.bounds.size.height
Amul4608
  • 1,390
  • 14
  • 30
1

CGFloat width = [[UIScreen mainScreen] bounds].size.width; CGFloat height = [[UIScreen mainScreen]bounds ].size.height;

Himanshu jamnani
  • 316
  • 2
  • 10
0

For iPad split window, the [[UIScreen mainScreen] bounds] doesn't work, use [UIApplication sharedApplication].delegate.window.bounds instead.

yclod
  • 21
  • 2
-2

You can place these macros in your pch file and used at anywhere in project by using "SCREEN_WIDTH"

#define SCREEN_WIDTH                ((([UIApplication sharedApplication].statusBarOrientation == UIInterfaceOrientationPortrait) || ([UIApplication sharedApplication].statusBarOrientation == UIInterfaceOrientationPortraitUpsideDown)) ? [[UIScreen mainScreen] bounds].size.width : [[UIScreen mainScreen] bounds].size.height)

and "SCREEN_HEIGHT"

#define SCREEN_HEIGHT               ((([UIApplication sharedApplication].statusBarOrientation == UIInterfaceOrientationPortrait) || ([UIApplication sharedApplication].statusBarOrientation ==   UIInterfaceOrientationPortraitUpsideDown)) ? [[UIScreen mainScreen] bounds].size.height : [[UIScreen mainScreen] bounds].size.width)

Example of using:

CGSize calCulateSizze ;
calCulateSizze.width = SCREEN_WIDTH/2-8;
calCulateSizze.height = SCREEN_WIDTH/2-8;
m4n0
  • 29,823
  • 27
  • 76
  • 89
Anny
  • 509
  • 1
  • 5
  • 14
  • Can you please indent your code according to the markdown format? Currently this was flagged as "low quality" by community users in the review queue. – m4n0 Nov 18 '15 at 06:36