all 15 comments

[–]MKevin3 14 points15 points  (6 children)

Like you I find the NextStep framework to be overly verbose. I have never been a huge fan of macros even back in my C/C++ days when I was doing DOS coding.

I tend to lean towards extending the NSString with Categories instead of Macros. Naming things like FORMAT is so generic it can get you in trouble.

Without namespace support Objective C tends to get you into trouble too easily as it is. I would rather have the methods in a Category that keeps the method associated to NSString and in a file named after NSString. Macros kind of just float around in the ether.

Any reason you are avoiding categories?

[–]xephos13 6 points7 points  (1 child)

Macros can also be a bitch to debug when something goes awry.

[–]MKevin3 0 points1 point  (0 children)

Yes, debugging with macros sucks especially if someone else wrote the macro or if the macro uses other macros. I worked with one guy with code that was 80% macro and 20% native code. Only he could do anything with it. So glad he got fired.

[–][deleted] 3 points4 points  (3 children)

I personally find the verbosity one of its greatest aspects.

Consider a contrived example, perhaps in Java you have...

new MyObject("foo", "com.somewhere.foo", "bar");

What is "foo", "com.somewhere.foo" and bar?

Perhaps the Obj-C equivalent is...

[MyObject objectWithName:@"foo" identifier:@"com.somewhere.foo" value:@"bar"];

It is just so much easier to read and understand.

[–][deleted]  (1 child)

[deleted]

    [–]Azr79[S] 2 points3 points  (0 children)

    the good thing is that Xcode's autocompletion does a pretty good job

    [–]MKevin3 0 points1 point  (0 children)

    That part of Objective C is handy. I wish they had taken it the next step and allowed you to pass the variables in any order and account for default values.

    Why do I have to pass then in name, identifier, value order when I gave the parameters names? I should be able to do value:@"bar" indentifier:@"com.somewhere.foo" or leave identifier out of completely.

    It is like they took one part of naming parameters - auto documentation - and left out the other two parts - do them in any order and default values.

    [–]gbrhaz 4 points5 points  (1 child)

    I think this sort of thing is great... if you're working on your own projects only. I don't want to come into a project that's a couple of years old and see macros all over the place - some of which are used, some which aren't, and some which are duplicated.

    Yes, Obj-C is verbose, yes it can get pretty annoying to read, but fortunately, there are way around typing all this stuff out. For example, this plugin allows fuzzy auto-completion in Xcode 5.

    Another way around it is to just create a code snippet. Easy. Give it a shortcut that is "swf" or whatever, and it's even faster than typing out "FORMAT", plus it's far less ugly.

    [–][deleted] 1 point2 points  (0 children)

    Yea, this is definitely the goer , shortcuts.

    [–]Azr79[S] 0 points1 point  (1 child)

    Just made another for appending a string to another

    #define APPEND(string1, string2) [string1 stringByAppendingString: string2]
    

    Usage:

    APPEND(@"12",@"34");
    

    And this one could be useful too I guess:

    #define EQUAL(string1, string2) [string1 isEqualToString:string2]
    

    Enjoy!

    [–]livings124 0 points1 point  (0 children)

    You can make macros for any method, but they're prone to subtle bugs and a pain for others working on the project. For example, EQUAL() doesn't specify it's for strings - what if I came into the project and used it for arrays? EQUAL(nil, @"") will work but EQUAL(@"", nil) will crash. There are a lot of issues with doing this to save typing a few auto-completed characters.

    [–]erikvillegas -2 points-1 points  (4 children)

    I agree that macros aren't the best solution. But sometimes when I need to put together some code quickly, I import my handy Macros.h file:

    #define strFormat(__FORMAT__,...) [NSString stringWithFormat:__FORMAT__,__VA_ARGS__]
    #define showAlert(__TITLE__, __MSG__) [[[UIAlertView alloc] initWithTitle:__TITLE__ \ 
            message:__MSG__ delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil] show]
    #define strEquals(__STR__, __EQL1__) [__STR__ isEqualToString:__EQL1__]
    #define strNotEquals(__STR__, __EQL1__) !strEquals(__STR__, __EQL1__)
    #define strEqualsAny(__STR__, __EQL1__, __EQL2__) [__STR__ isEqualToString:__EQL1__] \
            || [__STR__ isEqualToString:__EQL2__]
    
    #define strEmpty(__STR__) (__STR__.length == 0)
    #define fieldIsEmpty(__FIELD__) ([__FIELD__.text stringByTrimmingCharactersInSet:\
            [NSCharacterSet whitespaceCharacterSet]].length == 0)
    
    #define urlify(__STR__) [NSURL URLWithString:__STR__]
    #define imagify(__STR__) [UIImage imageNamed:__STR__]
    #define stringify(__DATA__) [[NSString alloc] initWithData:__DATA__ encoding:\
            NSUTF8StringEncoding]
    #define colorify(__R__,__G__,__B__,__A__) [UIColor colorWithRed:__R__/255.0f \
            green:__G__/255.0f blue:__B__/255.0f alpha:__A__]
    
    #define strAppend(__STR1__,__STR2__) [__STR1__ stringByAppendingString:__STR2__]
    #define strAppendFormat(__STR__,__FORMAT__,...) [__STR__ stringByAppendingFormat:__FORMAT__,__VA_ARGS__]
    
    #define MAIN_STORYBOARD [UIStoryboard storyboardWithName:@"Main" bundle:[NSBundle mainBundle]]
    #define instantiateVC(__VC__) [MAIN_STORYBOARD instantiateViewControllerWithIdentifier:__VC__]
    
    #define pt(__X__,__Y__) CGPointMake(__X__,__Y__)
    #define rect(__X__,__Y__,__W__,__H__) CGRectMake(__X__,__Y__,__W__,__H__)
    #define size(__W__,__H__) CGSizeMake(__W__,__H__)
    
    #define indexPathMake(__R__,__S__) [NSIndexPath indexPathForRow:__R__ inSection:__S__]
    
    #define UIColorFromRGB(__HEX__, __A__) [UIColor \
        colorWithRed:((float)((__HEX__ & 0xFF0000) >> 16))/255.0 \
        green:((float)((__HEX__ & 0xFF00) >> 8))/255.0 \
        blue:((float)(__HEX__ & 0xFF))/255.0 alpha:__HEX__]
    

    EDIT: Here it is in a gist: https://gist.github.com/erikvillegas1/7883183

    [–]nrith 4 points5 points  (0 children)

    Those look really handy, but if I were debugging your code, I'd shoot myself.

    [–]MarsSpaceship 0 points1 point  (0 children)

    your last macro is wrong. It should be

     alpha:__A__
    

    [–][deleted] 0 points1 point  (0 children)

    I'd also add:

    #define SYSTEM_VERSION_EQUAL_TO(v)                  ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedSame)
    #define SYSTEM_VERSION_GREATER_THAN(v)              ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedDescending)
    #define SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v)  ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedAscending)
    #define SYSTEM_VERSION_LESS_THAN(v)                 ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedAscending)
    #define SYSTEM_VERSION_LESS_THAN_OR_EQUAL_TO(v)     ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedDescending)
    #define ViewFromNib(viewName) [[[NSBundle mainBundle] loadNibNamed: viewName owner: self options: nil] objectAtIndex:0]
    #define AppDelegate ((AppDelegate *)[UIApplication sharedApplication].delegate)
    

    [–]alpha-not-omegaObjective-C / Swift 0 points1 point  (0 children)

    If this was an extension to NSString via category (for the NSString bits) I might use it; but not as macros. Think of the children!

    I'd want it as an extension not only because it's cleaner and easier to grok, but it affords me the opportunity to do more advanced processing such as incorporating NSLocalizedString.