Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
NSHipster Call for Tips & Tricks!

Howdy howdy, NSHipsters!

If you alloc init an NSCalendar, you'll notice that New Year's Eve falls on a Monday this year, a.k.a. "the day NSHipster is published every week". What fun!

So in celebration of the upcoming year++, I thought it'd be fun to compile a list of some of your favorite tips and tricks of the trade. Submit your favorite piece of Objective-C trivia, framework arcana, hidden Xcode feature, or anything else you think is cool, and you could have it featured in the year-end blowout article. Just comment on this gist below!

Here are a few examples of the kind of things I'd like to see:

Again, just comment on this Gist below with your submission.

Can't wait to see what y'all come up with!

jaykz52 commented Nov 26, 2012

Not all that esoteric, but using the ObjC runtime to "mixin" new properties on existing classes via associative references can be fun:

// header
@interface NSObject (PornName)

@property (nonatomic, strong) NSString *pornName;


// implementation
#import <objc/runtime.h>

static char const * const PornNameKey = "PornNameKey";

@implementation NSObject (PornName)

@dynamic pornName;

- (NSString *)pornName {
    return objc_getAssociatedObject(self, PornNameKey);

- (void)setPornName:(NSString *)pornName {
    objc_setAssociatedObject(self, PornNameKey, pornName, OBJC_ASSOCIATION_RETAIN_NONATOMIC);

mayoff commented Nov 26, 2012

Put this in your .lldbinit:

command regex rd 's/^[[:space:]]*$/po [[UIApp keyWindow] recursiveDescription]/' 's/^(.+)$/po [%1 recursiveDescription]/'

Now you can just type rd at the (lldb) prompt to get a dump of your entire view hierarchy. Or you can type rd self.view to get a recursive dump of self.view.

Avoid using +[load] class methods, especially for preloading resources from disk. All of these methods will be called before the applicationDidFinishLaunching: and may greatly increase the launch time bow-wow! Really simple tip, but this problem pops up even in the best open-source frameworks.

How about clearing up the purpose of all the different pre-processor types? I am still unclear as to why we have nil/Nil/NULL, YES/TRUE/true etc, and generally just use them based on the conventions I see in other code.

mayoff commented Nov 27, 2012

In theory, nil is the null pointer with type id and Nil is the null pointer with type Class. In practice, both are defined to plain old null (with no special type) in <objc/objc.h>.

mayoff commented Nov 27, 2012

Want to print the elements of a CGPathRef from the debugger?

p (void)CGPathPrint(pathRef, 0)
alextud commented Nov 27, 2012

A much easier way to measure a piece of code:

NS_INLINE void MVComputeTimeWithNameAndBlock(const char *caller, void (^block)()) {
    CFTimeInterval startTimeInterval = CACurrentMediaTime();
    CFTimeInterval nowTimeInterval = CACurrentMediaTime();
    NSLog(@"%s - Time Running is: %f", caller, nowTimeInterval - startTimeInterval);

#define MVComputeTime(...) MVComputeTimeWithNameAndBlock(__PRETTY_FUNCTION__, (__VA_ARGS__))
alextud commented Nov 27, 2012

An example:

    for (NSEntityDescription *entity in [[[NSPersistentStoreCoordinator MR_defaultStoreCoordinator] managedObjectModel] entities])     {
        NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:[entity name]];
        NSLog(@"%@ - objects count - %d",  [entity name], [[NSManagedObjectContext MR_defaultContext] countForFetchRequest:fetchRequest error:nil]);

Not sure if hipster enough, but using code snippets effectively. I think they're underused for documentation

- enumerateObjectsWithOptions: usingBlock:

for the various collection objects. The magic about this is the option NSEnumerationConcurrent. It will enumerate different iterations of the loop concurrently. Useful in certain situations, dangerous in others. Think that makes it cool enough for NSHipsters.

mattt commented Nov 29, 2012

These are all awesome, guys. Thanks for the great tips! Keep it up!

0xced commented Dec 3, 2012

See function static id _target(id autoContentAccessingProxy) for accessing a private ivar. You should obviously never ship your app with such code but it may be helpful for debugging.

0xced commented Dec 3, 2012

extern NSString *const and weak linking does’t work the way you think it works, from

#import <Social/Social.h>

/* Compiled with iOS 6 SDK
 * Social.framework weak linked (Optional)
 * Run on iOS 5.1 (simulator and device)
 * Output is:
 * 0x0
 * About to crash
 * +++ EXC_BAD_ACCESS +++

int main(int argc, char *argv[])
        NSLog(@"%p", &SLServiceTypeFacebook);
        if (&SLServiceTypeFacebook)
            NSLog(@"About to crash");
            NSString *serviceType = SLServiceTypeFacebook; // crashes here with EXC_BAD_ACCESS (code=2, address=0x0)
            NSLog(@"Not reached %@", serviceType);
    return 0;
0xced commented Dec 3, 2012

Using NSPropertyListSerialization to implement base64 encoding and decoding in less than 50 lines with support for iOS 2.0 and OS X 10.5.

How about associated objects? You know it’s going down when you see this at the top of one of my files:

#import <objc/runtime.h>

static const void *kMyKey = &kMyKey;

In iOS 6 you can animate a constant property in NSLayoutConstraint:

viewConstraint.constant = ConstantValueFrom;
[view layoutIfNeeded];

viewConstraint.constant = ConstantValueTo;
[view setNeedsUpdateConstraints];

[UIView animateWithDuration:ConstantAnimationDuration animations:^{
     [view layoutIfNeeded];
0xced commented Dec 3, 2012

Printing NSCache usage information (tested on iOS only):

extern void cache_print(void *cache);

- (void) printCache:(NSCache *)cache
    cache_print(*((void **)(__bridge void *)cache + 3));

Use for debugging only!

mattt commented Dec 31, 2012

Thanks again, everyone, for your great submissions! These have now been compiled into this special New Year's Eve Edition of NSHipster. Cheers!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment