# Objective-C class for placing UI elements based on screen size

I'm always programmatically creating and laying out UI elements in multiple ViewControllers and I've wanted an easy way to get relevant Screen information (sizes/points) globally using a helper class.

I've created a FlexibleScreen class and would like some constructive feedback. In addition to the typical code review feedback of format, syntax, etc I would really like to know how well this solves my problem functionally and what suggestions you have about the design or what additional functionality I could add.

FlexibleScreen.h

#import <Foundation/Foundation.h>

@interface FlexibleScreen : NSObject

+(CGSize)getScreenSize;
+(CGPoint)getCenter;
+(CGPoint)getCenterWithY:(double)y;
+(CGPoint)getCenterWithX:(double)x;

@end


FlexibleScreen.m

#import "FlexibleScreen.h"

@interface FlexibleScreen()

@property (assign) CGRect bounds;
@end

@implementation FlexibleScreen

+(CGSize)getScreenSize
{
return CGSizeMake([[UIScreen mainScreen] bounds].size.width, [[UIScreen mainScreen] bounds].size.height);
}

+(CGPoint)getCenter
{
return CGPointMake([[UIScreen mainScreen] bounds].size.width/2, [[UIScreen mainScreen] bounds].size.height/2);
}

+(CGPoint)getCenterWithY:(double)y
{
return CGPointMake([[UIScreen mainScreen] bounds].size.width/2, y);
}

+(CGPoint)getCenterWithX:(double)x
{
return CGPointMake(x, [[UIScreen mainScreen] bounds].size.height/2);
}

@end


Implementing Code

#import "FlexibleScreen.h"


...

CGRect headerFrame = CGRectMake(0, 0, [FlexibleScreen getScreenSize].width, HEADER_HEIGHT);
CGRect footerFrame = CGRectMake(0, [FlexibleScreen getScreenSize].height-FOOTER_HEIGHT, [FlexibleScreen getScreenSize].width, FOOTER_HEIGHT);


...

[label setCenter:[FlexibleScreen getCenterWithY:0]];


UPDATE: As I used this more I realized I wanted it to be a lot simpler. Here is my latest version GitHub: UIScreen+Flexible.

Some thoughts on it:

1. Code: I'd suggest to create a Category on UIScreen. This is even more elegant than creating a separate class.

2. Naming: In Objective-C getter usually do not have the prefix "get".

3. General approach: Without knowing the background of your app and any detailed implementation, it's not common to layout UIViews relatively to the screen. As you're using UIViewControllers, any additional view should be added as a subview to the UIViewController's view. This ensures that layout and orientation changes are handled for you and are automatically being applied to all subviews by the UIViewController.

Consider using more of what Core Graphics gives you. There are methods along the lines of CGRectGetMaxX(rect), CGRectGetMidY(rect) and CGRectGetWidth(rect) that does that kind of basic math for you. It reads cleaner and other coders who are used to Objective-C will immediately recognize them and understand the code.

Also, there is some code duplication where you calculate the center x twice and the center y twice. You can introduce two private methods to get rid of that duplication (I've also removed the "get" prefix as it is not commonly used in Objective-C and switched to CGFloat instead of double).

(If you really want to get rid of code duplication then you can create a method to get the bounds of the main screen. I did so in the code below)

+(CGRect)screenBounds
{
return [[UIScreen mainScreen] bounds];
}

+(CGFloat)centerX
{
return CGRectGetMidX([self screenBounds]);
}

+(CGFloat)centerY
{
return CGRectGetMidY([self screenBounds]);
}

+(CGPoint)center
{
return CGPointMake([self centerX], [self centerY]);
}

+(CGPoint)centerWithY:(CGFloat)y
{
return CGPointMake([self centerX], y);
}

+(CGPoint)centerWithX:(CGFloat)x
{
return CGPointMake(x, [self centerY]);
}


Here are some changes I've made so far to FlexibleScreen (GitHub):

## 1. Status Bar Height

I also found that the status bar height plays a role into how much height is left on-screen if the status bar is present so I added this method which will be used by +getScreenSize to report an accurate screen size:

+(double)statusBarHeight
{
double statusBarHeight = 0;
if (![UIApplication sharedApplication].statusBarHidden){
statusBarHeight = [UIApplication sharedApplication].statusBarFrame.size.height;
}
return statusBarHeight;
}


## 2. Global Import FlexibleScreen

I also imported FlexibleScreen.h in *-Prefix.ch so that it was globally accessible without having to import in each file. I will eventually change FlexibleScreen to be a category like Florain Mielke suggested and that way I won't have to import it at all.