Rectangles

CGRect Tricks

CGRect is one of the most important structures used in building apps in iOS. After a year of working as iOS developer I found some CGRect tricks and useful tips that can help developers in their work. In this post I will list some tips and tricks about CGRect. Please If you know tips or tricks that will be useful, comment in this post.

Printing CGRect info:


If you want to print the values of CGRect for testing you can use NSStringFromCGRect:

CGRect frame = CGRectMake(10, 20, 100, 200);
NSLog(@"%@", NSStringFromCGRect(frame));
//output  {{10, 20}, {100, 200}}

You can also use NSStringFromCGPoint or NSStringFromCGSize. Also there is a function called CGRectFromString to get a CGRect from NSString but it should be in this format {{x,y},{w, h}}

Shrink CGRect:


To shrink a CGRect you can use

CGRectInset(rect, dx, dy)

that shrinks a given CGRect with dx horizontally and dy vertically in the two sides while keeping the center point without changing, for example:

CGRect rect = CGRectMake(10, 20, 100, 200);
NSLog(@"mid point: %f, %f", CGRectGetMidX(rect), CGRectGetMidY(rect));
//mid point of rect  (60.0, 120.0)
CGRect shrinked = CGRectInset(rect, 5, 10);
NSLog(@"%@", NSStringFromCGRect(shrinked));
//shrinked rect  {{15, 30}, {90, 180}}
NSLog(@"mid point: %f, %f", CGRectGetMidX(shrinked), CGRectGetMidY(shrinked));
//mid point of shrinked  (60.0, 120.0)

To apply the shrink with different insets for each edge, you can use UIEdgeInsetsInsetRect(rect, insets) that shrink a given rect with insets. Insets can be created using the function UIEdgeInsetsMake (top, left, bottom, right) and give it the margins for each edge. To summarize: this function increment the values with origin and decrement the size, for example:

CGRect rect = CGRectMake(10, 20, 100, 200);
    
CGRect shrinked = UIEdgeInsetsInsetRect(rect, UIEdgeInsetsMake(20, 8, 30, 40)); //(top, left, bottom, right)
NSLog(@"%@", NSStringFromCGRect(shrinked));
//shrinking rect  {{18, 40}, {52, 150}}

So, if we have a rect(x, y, w, h) with insets (top, left, bottom, right) => rect(x+left, y+top, w-left-right, h-top-bottom)

CGRect Union


CGRectUnion(rect1, rect2) is used to get the union of 2 rectangles, a rectangle that includes the 2 given rectangles.
CGRectUnion is UIScrollView’s best friend because when you use UIScrollView with bunch of subviews and want to set the content size of scroll view, so you can union the top-left frame and bottom-right frame to get the whole size, for example:

//Get rectangle that contains all subviews
CGRect theUnion = CGRectUnion(topLeftView.frame, bottomRightView.frame);
    
//Adding padding to top and bottom (don't forget, negative values make padding not an inset)
CGRect newFrame = CGRectInset(theUnion, 0, -20);
//adjust scroll content size
scrollView.contentSize = newFrame.size;

Dictionary Representation of CGRect:


Get dictionary representation of CGRect to be stored in plist, for example:

CGRect frame = CGRectMake(10, 20, 100, 200);
    
CFDictionaryRef frameDicRef = CGRectCreateDictionaryRepresentation(frame);
NSDictionary *dic = [NSDictionary dictionaryWithDictionary:(__bridge NSDictionary *)frameDicRef];
CFRelease(frameDicRef);
NSLog(@"%@", dic);
    /**
     {
        Height = 200;
        Width = 100;
        X = 10;
        Y = 20;
     }
     */

Storing CGRect in Objective-C classes:


To store CGRect in Objective-C classes like NSArray or NSMutableArray, you have to convert it to NSValue, for example:

    CGRect rect1 = CGRectMake(10, 20, 100, 200);
    CGRect rect2 = CGRectMake(12, 20, 150, 220);
    //Get NSValue from CGRect
    NSMutableArray *frames = [NSMutableArray array];
    [frames addObject:[NSValue valueWithCGRect:rect1]];
    [frames addObject:[NSValue valueWithCGRect:rect2]];
    
    //To get CGRect from NSValue use:
    CGRect frame = [frames[0] CGRectValue];
    NSLog(@"%@", NSStringFromCGRect(frame));
    //output {{10, 20}, {100, 200}}
  • http://bolica.net Ahmed Bolica

    Good job Hossam