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