Hi this is Marin - the author of Touch Code Magazine, I hope you are enjoying my tutorials and articles. Also if you need a bright iPhone developer overseas contact me - I do contract work. Here's my LinkedIn profile
CGPointMake, CGSizeMake, etc. shortcuts

I don’t come from a C background (when it was the time to choose I went with Pascal – it was pretty hot at the time), so some C style stuff in Objective-C are kind of mysterious to me – and I guess also for many of you.

One of those oldies are the structures. Unfortunately they are all over the place – CGPoint, CGSize and CGRect for example. And it always annoys me to have all these long function names to write like CGPointMake, CGSizeMake and CGRectMake. While digging through some 3rd party libraries I noticed something that looks like the ultimate solution for me and my functions hurdle.

In C you can have something called – structure initializer – pretty awesome thing. Let’s have a look how you can create a CGPoint using an initializer:

CGPoint p = {25.0f, 12.0f};
CGPoint p1={10,200};

Pretty short and cool too!

You can also give it a try to see that the point is exactly set as you wanted:

NSLog(@"pt: %@", NSStringFromCGPoint(p));

Awesome! Let’s have a look at a CGSize initializer:

CGSize  s = {10,20};

Alright! Great stuff! How about a CGRect though? It’s a structure made out of other structures – a CGPoint and a CGSize… Hmmm … Let’s just give it a try:

CGRect  r = {10,10,200,40};

Wow. How that works? All the values are just fed into the structure’s components one after another…

So … it doesn’t work only for the ones we already had a look at, but also for all kind of structures – you just need to know the exact order the variables inside the structure are defined in and just feed values in.

You can also dynamically cast these if you need to, like so:

(CGRect){10,10,200,40};

That’s pretty much all about the structure initializers, I love them and hopefully they help you out too.

The post was originally published on the following URL: http://www.touch-code-magazine.com/cgpointmake-cgsizemake-etc-shortcuts/

 

  ·

 


Marin Todorov

is an independent iOS developer and publisher. He's got more than 18 years of experience in a dozen of languages and platforms. This is his writing project.
» Contact    » Add Marin on Google+

  1. jo on Monday 20, 2012

    i don’t think this is a good idea.
    if apple changes anything in the CGPoint structure all code will become unusable. better use a #define for CGPointMake like in cocos2d for example.

  2. Marin on Monday 20, 2012

    Alright- that’s a very good point against

  3. I on Monday 20, 2012

    It’s extremely unlikely that Apple would ever change basic structs like these. It would break binary compatibility for all existing apps and libraries. And what would they even change? Swap the x and y fields? Add a z field? Swapping doesn’t make any sense and if they wanted a 3D point, they would just make a new struct. A change in data type (float -> double) wouldn’t break the C99-style initializers as the ordering is the same, and this actually already happens when building for a 64-bit Mac.

    These structs are fundamental enough that you can expect them to never change in a source-incompatible way.

  4. Karl on Monday 20, 2012

    I suppose the other problem is use. For example, CGRectMake is not the only CGRect macro. There’s -Zero -IsEmpty, IsNull, and all the -Get…’s. To be consistent in your code, it would seem better to use the macro..

  5. Kevin on Monday 20, 2012

    There is still the issue of readability. In classic C form, the function as used in code is just a list of unnamed parameters:

    CGRect rect = CGRectMake(10.f, 20.f, 480.f, 360.f);

    Now I know what each of those represent from seeing that function a zillion times, but compared to the natural language readability of Objective C, it’s pretty obscure looking. The above style of struct initialization isn’t much better, though at least it breaks up the origin and size:

    CGRect rect = {{10.f, 20.f}, {480.f, 360.f}};

    These eliminate a function call as well! While that is quite a micro-optimization for normal code, it has some useful consequences. For example, you can now declare these as compile-time constants. But what about readability? C99 to the rescue!

    CGRect rect = (CGRect){
    .origin = (CGPoint){
    .x = 10.f,
    .y = 20.f,
    },
    .size = (CGSize){
    .width = 480.f,
    .height = 360.f,
    }
    };

    or, shortening things up a bit:

    CGRect rect = (CGRect){
    .origin.x = 10.f,
    .origin.y = 20.f,
    .size.width = 480.f,
    .size.height = 360.f,
    };

    I especially like that notation for compile-time constants, as it’s easy to read and not getting in the way of the flow of code (where the multiple-line approach may be a nuisance). Also all these struct initializer methods make it easy to reuse a CGPoint or CGSize for multiple CGRect structs – just set .origin or .size!

  6. Matt on Monday 20, 2012

    You could argue that they are not a list of unnamed parameters as they would be constants or variables, with meaningful names. Readability is severely reduced by arbitrary constants.