Time-Saving TextExpander Snippets for Xcode

I literally cannot get through a work day without using TextExpander. It’s one of the first things I install on a new Mac. Over the years I’ve built up a lot of time-saving Xcode TextExpander snippets. I’ve compiled all the universally applicable ones into this exported backup. Here are some of the highlights from my collection:

slef, vodi

self, void

These fix my two most common typing mistakes in Xcode.

ttableview

This fills out an entire stub .m file for a table view controller.

First copy the name of your new UITableViewController subclass into the clipboard. Delete all the text from the stock .m file that’s created. Then type ttableview. It expands into a bare-bones table view controller. It’s especially handy when you know you won’t need to uncomment the editing methods of the default Xcode template.

ssingleton

+ (instancetype)sharedInstance {
    static dispatch_once_t once;
    static %clipboard * sharedInstance;
    dispatch_once(&once, ^ { sharedInstance = [[self alloc] init]; });
    return sharedInstance;
}

Used prudently, a singleton isn’t a liability. But if you’re going to use it, make sure you’re initializing it correctly: once and in a thread-safe manner. Like the ttableview one above, start by copying your class name into your clipboard.

dmain

dispatch_async(dispatch_get_main_queue(), ^{

});

This is the preferred way to kick off a block of code to be executed on the next turn of the main thread runloop. No, _async is not a typo. I have never had a need to use _sync, and often just the opposite: the synchronous call can cause terrible race conditions.

dbg

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

});

dafter

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 3 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
        
});

I use this one a lot when debugging new code, for example, when simulating a long-running background operation before that background code is available to build against.

wself

typeof(self) __weak weakSelf = self;

People have all kinds of solutions for this problem, but I prefer to use a native solution over a third-party dependency when it’s convenient to do so. This snippet makes it trivial.

kkvo

static void * JTSSomeContext = "JTSSomeContext";

#pragma mark - KVO

- (void)addObservationsTo:(NSObject *)object {
    [object addObserver:self forKeyPath:@"keyPath" options:NSKeyValueObservingOptionNew context:JTSSomeContext];
}

- (void)removeObservationsFrom:(NSObject *)object {
    [object removeObserver:self forKeyPath:@"keyPath" context:JTSSomeContext];
}

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
    if (context == JTSSomeContext) {
        if (object == self.myObject) {
            if ([keyPath isEqualToString:@"keyPath"]) {
                // Stuff
            }
        }
    } else {
        [super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
    }
}

I don’t ever use the result of this snippet as-is — it needs a specific target class and key path — but it sure saves a helluva lot of time and potential errors, like forgetting to call super.

fformat

[NSString stringWithFormat:@""]

This one even drops your cursor between the double quotes in the format string.

llocal

NSLocalizedString(@"", @"DESCRIPTION_HERE")

This one, like fformat above, drops your cursor between the first double quotes. You’re less likely to forget to localize a string if you make this snippet a muscle memory.

lltab + suffix variants

NSLocalizedStringFromTable(@"

If my project is using NSLocalizedStringFromTable() instead of NSLocalizedString(), I use the lltab snippet in combination with a project-specific suffix snippet. For example, in Unread I use lltun which turns into:

", @"Unread", nil)

The workflow is then lltab + text + lltun, the latter of which becomes a muscle memory pretty quickly as I get deep into a project.

ccoding

#pragma mark - NSCoding

- (void)encodeWithCoder:(NSCoder *)aCoder {
    [NSCoder encodeObjectIfNotNil:_item forKey:@"key" withCoder:aCoder];
}

- (id)initWithCoder:(NSCoder *)aDecoder {
    self = [super init];
    if (self) {
        _item = [aDecoder decodeObjectForKey:@"key"];
    }
    return self;
}

bgtask

 UIBackgroundTaskIdentifier backgroundTaskIdentifier = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
        // handle expiration
   }];
    
    // Do some long running operation then:

   [[UIApplication sharedApplication] endBackgroundTask:backgroundTaskIdentifier];

|  31 Aug 2014