Create a gist now

Instantly share code, notes, and snippets.

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
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;

@end

// 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);
}

@end
@mayoff
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.

@shpakovski

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.

@ryanmaxwell

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
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
mayoff commented Nov 27, 2012

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

p (void)CGPathPrint(pathRef, 0)
@alextud
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();
    block();
    CFTimeInterval nowTimeInterval = CACurrentMediaTime();
    NSLog(@"%s - Time Running is: %f", caller, nowTimeInterval - startTimeInterval);
}

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

An example:

MVComputeTime(^{
    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]);
    }
});
@MaxGabriel

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

@joelparsons
- 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
Owner
mattt commented Nov 29, 2012

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

@0xced
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
0xced commented Dec 3, 2012

extern NSString *const and weak linking does’t work the way you think it works, from https://gist.github.com/3725528:

#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[])
{
    @autoreleasepool
    {
        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
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.

@SlaunchaMan

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;
@shpakovski

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
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
Owner
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