Sharpening the Yak

Mixed Metaphors

The title of this blog post is a mixed metaphor. It’s a mashup of two common programmer idioms, sharpening the axe, and shaving the yak. I’ve been doing both this week, but before I get into that, I’ll define the terms.

Sharpening the Axe actually comes from a quote attributed to Abraham Lincoln: “Give me six hours to chop down a tree and I will spend the first four sharpening the axe.” When googling around for how this applies to programming, it seems a lot of folks have (for some unfathomable reason) latched onto the phrase “sharpening the saw” instead. I can think of four general categories of specific activities this could mean:

  • direct study — Ie., reading a book on a language or API, or reading and/or studying some relevant source code. Anything that directly applies to some programming task you have to undertake.
  • indirect study — This could include reading more generally about programming or related “industry” news, or learning a new language you will not immediately be using, or any other research not directly related to your current task list but (hopefully) teaching you something tangentially related.
  • architecting — This could be formal, in that you’re writing a document or outline, or putting together a task list, or just more generally thinking about the task(s) you have at hand. (I find I do my best architecting in the shower.)
  • practice — Writing code, but not code you will be using. I’m not much for this one, but I’ve heard a lot of good programmers say they write something once, throw it away, then write it for real. That sounds like a lot of extra work to me, but who knows, it is definitely easier to write something the second time. I’m not sure it’s guaranteed to be better though.

Yak Shaving is a more complex and subtle problem. Jeremy H Brown defined it in a usenet post in 2000 as “what you are doing when you’re doing some stupid, fiddly little task that bears no obvious relationship to what you’re supposed to be working on, but yet a chain of twelve causal relations links what you’re doing to the original meta-task.” The programmers Stack Exchange has more on the definition and history of the term yak shaving.

So what have I been doing this week?

I’m working on iCloud syncing for ActionGo, my next game for Apple TV and iOS. In a way, this is already shaving the yak, since I’m really only working on that because the Apple TV doesn’t support filesystem saving, and iCloud is their recommended solution. But after only a day or so of work, I found out that it does support NSUserDefaults key/value saving. (Up to 600 K, plenty for a saved game or two.) Since I’d already planned on implementing iCloud as key/value, so long story short, now I’m doing both. (Which is of course better, because it’ll work offline too, just without the syncing.)

But I’ve never done iCloud syncing before. *queue sharpening sounds* There are at least a couple of ways you can store data there, key/value, or document-based. Key/Value is definitely preferred for my use-case (a bit of state data for games in progress, and storing overall meta-game statistics), so I focused on that, but even then there are a bunch of different ways to go about it. Consensus seems to be that it’s really easy to get working, but almost all the blog posts and resource sites I read focused on that initial experience and I didn’t end up finding anyone who went into best practices.

So here’s the yak shaving rabbit hole (oooh, a third metaphor?): I’m using Generic Game Model for game state, which already had saving implemented on iOS using the built-in saving functionality that BaseModel provides. But it turns out that I was using an old version of BaseModel, so I had to update that. Then I wasn’t happy with how BaseModel implements its NSUserDefaults storage, so I re-wrote that. Then I wrote a wrapper that handles the syncing to iCloud whenever a key is added to NSUserDefaults (storing an associated NSDate value also, so I can just keep whatever’s latest), and only just now I’m finally getting around to testing. (Only I’m not so much, since I’m writing this post right now instead.)

When is your axe too sharp?

While “researching” this post *more sharpening sounds*, I ran into this critique of Axe Sharpening from a java.net blog post back in 2005:

But for me, the big problem with “axe sharpening” is that it’s recursive, in a Xeno’s paradox kinda way … to sharpen the axe, you need a sharpening stone… But to get there, you need to build a dog sled… But to use a dog sled I need snow, so I need to go to town to get a snow cone machine. I grab my trusty yak to help you haul the machine from town. But it’ll be summer before I get to town, and I don’t want the yak to get to hot, so I shave the yak. In mid February, I proudly lead my shining, bald, shivering yak into my quarterly progress review…

Hilarious.

An Introduction to Generic Game Model

Here are my slides from the presentation I gave tonight at the MN Cocoaheads group about my open source 2D game framework, Generic Game Model.

Description
Martin Grider will share and discuss a few classes he re-uses from project to project allowing him to rapidly flush-out 2D games. The classes themselves are not all that notable, as most developers could probably re-create them in an afternoon, but the techniques are particularly suited to rapidly prototyping turn-based games. He’ll discuss some of his favorite rapid prototyping techniques, as well as talk about “juicing” animations in UIKit, (with a bit of quartz core, as well as a bunch of external libraries thrown in for good measure).

Commentary
As you can see, if you looked through the slides, I have already used this code in a rather large number of projects in the last two years. I was surprised myself, to be honest. At least 8 projects use this thing, 3 of which are in the app store.

My first Cocoapod
While prepping for the talk, I also turned the project into a Cocoapod. I had played around with cocoapods once before, only long enough to install it and run pod install on a test project, (a process which is, if anything, too easy!), but actually creating a pod myself was a new experience, and bit more work than I’d expected going into it. Anyway, you can now add pod 'GenericGameModel' to your projects to try it out for yourself.

Thanks to Bob McCune for running the show and letting me speak!

NSNumber+XYCoordinates

So I occasionally have the problem where I want to store a bunch of x,y coordinates. I have solved this a number of ways in the past, but most recently had the idea of writing a category on NSNumber that simply stores two 16 bit integers, bitshifted together. So without further ado, here’s the github project for NSNumber+XYCoordinates.

My first version of this I couldn’t get negative numbers to work, but after some patient binary math explaining today at the coffee shop from my friend Matt, I finally got it to support numbers between -32767 and 32767.

Essentially, my category just adds the following methods:

NSNumber *xyNum = [NSNumber numberWithX:10 andY:10];
int x = [xyNum xValue];
int y = [xyNum yValue];

This seems to work pretty great, and is way less annoying than my previous favorite technique, which was to convert between NSString and CGPoint all the time.

So I got to thinking tonight… this should be fast, right? But I have no idea how fast, really, or how to compare it. So I wrote some test cases. Each of them assigns and then reads back out again some number of sequential integers using various techniques that I’ve used in the past. I compiled the following lists for different numbers of values:

100 Values
CGPointToNSString – size of 100 string objects in multidimensional array is 2263 (0.002 seconds).
NSDictionary – size of 100 objects in NSDictionary is 2413 (0.001 seconds).
NSSet – size of 100 objects in set is 1545 (0.004 seconds).
NSNumber+XYCoordinates – size of 100 objects in multi-dimensional array is 2033 (0.001 seconds).

10,000 Values
CGPointToNSString – size of 10000 string objects in multidimensional array is 241803 (0.162 seconds).
NSDictionary – size of 10000 objects in NSDictionary is 289593 (0.076 seconds).
NSSet – size of 10000 objects in set is 199798 (0.044 seconds).
NSNumber+XYCoordinates – size of 10000 objects in multi-dimensional array is 203503 (0.046 seconds).

1,000,000 Values
CGPointToNSString – size of 1000000 string objects in multidimensional array is 31702088 (10.187 seconds).
NSDictionary – size of 1000000 objects in NSDictionary is 38735561 (121.886 seconds).
NSSet – size of 1000000 objects in set is 25866828 (118.003 seconds).
NSNumber+XYCoordinates – size of 1000000 objects in multi-dimensional array is 25919832 (114.918 seconds).

You see that the technique compares favorably against CGPointToNSString, at 100 and 10,000 values, but somehow, the CGPointToNSString technique just blows it out of the water in terms of speed when we get to a million objects. (Still much smaller though.) I don’t fully understand this, but I guess maybe the C API is faster at high volumes? Let me know if you think you might have some insight!

How long does it take to make an AdHoc build?

An AdHoc build is how you get iOS apps onto an Apple device without going through the App Store. They are typically used for testing. I was asked this question recently, and spent 15 minutes writing up this reply, so I thought I’d post it here. The obvious caveat is that it can of course vary from project to project. A bigger more complex project has more “moving parts” that can need fiddling with when creating a build.

So… How long does it take to make an iOS AdHoc build?

I use TestFlight to distribute my AdHoc builds, and typically, I tell clients an AdHoc build takes between 15 and 30 minutes to complete. Thankfully this work “stacks” quite a bit, so doing a few of them at once might only take 20 or 30 minutes. This process basically just involves opening the project, verifying a few settings related to provisioning profiles and “targets”, building an “Archive” of the project, uploading the new build to TestFlight, and writing some release notes as well as picking the users to receive the build. (Thanks to the awesome TestFlight OSX app, those last two steps can be done while the upload is in progress.)

This assumes, however, that all the devices are already registered with TestFlight. Everything takes longer when I need to add additional devices. This stacks too, so adding 1 to 10 or 15 new devices only takes another 15 or 20 minutes. The main additional thing that I need to do in this case is upload the device identifiers for the new devices to Apple’s provisioning portal, and download a new (or updated) provisioning profile that includes those new devices. This additional work has to happen BEFORE I can make the AdHoc build for those devices.

What I find frustrating is when all these tasks are split up over the course of hours or days. For instance, when I’m asked to send a build to some new individual, but they’ve never used TestFlight, and aren’t yet registered there. Then I have to send them an invite, wait for them to accept the invite, wait again for them to register their device, then finally I can get their identifier and begin the process. This means either waiting for the new person before creating the build (sometimes this can take days, of course!), or just creating two builds, one with the devices I already have, and another when I get all the important information from the new person. Considering the adage that a “a 15 second interruption results in 15 minutes of programmer downtime” (which is more or less verifiable), these build requests can really add up to lost productivity for me.

One final note about what AdHoc builds are not.

After an app is in the app store, unless you are testing a new version, you should really be using that version, and not an AdHoc build. There are many reasons for this, but notably: 1) AdHoc builds will expire when the provisioning profile expires. 2) You get the peace of mind that what you are seeing is what your users are seeing. 3) You will get the updates via the app store, as your users do. 4) You can instal the app on multiple devices without needing to provision all of them. Don’t forget about using promo codes to get “free” versions of apps to your testers or employees after an app goes live! (In my experience, you rarely use all of them for press as you should, and you get a “fresh” batch after each update anyway.)

AdHoc builds are an integral part of iOS app development, but creating them is annoying to me because it’s not programming. Of course, neither is wring this blog post.

How to change the color of a transparent image in iOS

This is probably as good a time as any to mention the next project I’m working on. It’s a turn-based (yes, asynchronous) board game. I decided to work with an existing game, because I wanted it to be really awesome, but also really simple. It’s an abstract game that is well respected in some circles. (I’m not going to reveal which one just yet.) Anyway, I’m working closely with the game’s designer, as well as with the same AI programmer I worked with on For The Win. The main goal of the project is to get the async code really solid, so I can feel like I really understand how it works, and re-use it in future projects.

Anyway, I think I’m also going to try something I’ve wanted to do before, and that is implement a variable color scheme for the app. Essentially you’ll be able to change the app’s background color, and that will also programmatically change the color scheme. I spent about two hours and had the basic color change functionality working pretty great with some code based on an already pretty great open-source color picker.

Anyway, one tiny piece remained… I would need to be able to programmatically tint images I get from the designer on this project. He’s going to give me some icons and other assets that we’ll no doubt want to change colors along with the rest of the app.

Some unknown number of hours later, I’ve got a solution. The number of hours is probably around the same as the number of lines of code in the solution. Here are those lines, implemented in the drawRect: method of a UIView subclass with a UIImage property named image, and a UIColor property named colorToChangeInto.


CGContextRef context = UIGraphicsGetCurrentContext();

CGContextScaleCTM(context, 1, -1);
CGContextTranslateCTM(context, 0, -rect.size.height);

CGImageRef maskImage = [self.image CGImage];
CGContextClipToMask(context, rect, maskImage);

[_colorToChangeInto setFill];
CGContextFillRect(context, rect);

I hope this is fairly straight forward. These few lines stand on the backs of many stack overflow answers. (And I did actually write this up into a question of my own at some point.) None of the other answers were exactly what I needed, but several of them got me close. In the end, I was super frustrated because it really seemed like I should be seeing what I wanted to see, but the background of the image was black… turned out I was instantiating the image in IB (in a storyboard), but I hadn’t set the background color. Somehow that defaulted to black. That particular issue probably wasted me an hour or two.

And then writing this blog post… another half-hour, at least.

MailChimp signups from iOS – How to add a subscriber to a MailChimp Group

This week, I’ve spent some of my time integrating MailChimp into the client work I’m doing. I found some of the documentation lacking, and there is no example for how to add your email signups to a MailChimp’s list “Group”, so I thought I’d document that here.

(Astute readers who are actually reading from chesstris.com will notice the fact that I’ve got a MailChimp signup form on Chesstris.com also. I haven’t done anything with it, and so far, I’m the only person who has signed up, but it’s there. I’m still sort of trying it out.)

MailChimp has an iOS SDK they call ChimpKit, which is available up on github. In general, it’s a great SDK, but the README has some installation instructions that are both incomplete and also pretty stupid, as far as I’m concerned. After fiddling around with it for a couple of hours yesterday, I’ve concluded that there is no reason to include their sample project as a git submodule of your project. The instructions I’m going to suggest basically don’t do that, so if you are ultra concerned with keeping up to date with the ChimpKit project (keep in mind it hasn’t been updated since 9 months ago), then read-no-further, and go figure out how to actually use the classes in their sample project yourself (since that’s what’s missing from their instructions). Personally, I think git submodules are a PITA, and not worth the effort anyway.

OK, so what you really want to do is the following:

1) Download the ChimpKit code. You can clone it on github, or just download, your preference.

2) ChimpKit requires SBJson, so you’ll need to include that project’s files in your project. You can do this as a git submodule if you really want, but you already know how I feel about those. You can also just add the files to your project and be done with it.

3) Grab just the files in ChimpKit’s “Core” folder and drag them into your project (or use the “Add files…” dialogue). Personally, I like to organize code in my projects in a certain way, so I copied the directory into my project’s “Externals” directory, and renamed it from “Core” to “ChimpKit”.

4) If you don’t care about adding your subscriber to a group, you just need to do the following:

4.a) Add the include: #import "SubscribeAlertView.h" to the top of your view controller or wherever.

4.b) Add this code somewhere, maybe after an IBAction or something.

SubscribeAlertView *alert = [[SubscribeAlertView alloc]
initWithTitle:@"Newsletter Sign-up"
message:@"To sign up for the newsletter please input your email address below."
apiKey:mailChimpAPIKey_
listId:mailChimpListID_
cancelButtonTitle:@"Cancel"
subscribeButtonTitle:@"Confirm"];
[alert show];

Of course you’ll need to define mailChimpAPIKey_ and mailChimpListID_, but both are strings. If you don’t know your list ID, you can find that on the mailchimp website. (Or by using the “lists” api method, and you can see an example of that below.)

…and you’re done!

5) But assuming you care about adding your subscribers to the group, there are two ways you could go. You could modify the code in SubscribeAlertView, or implement the subscribe form yourself. I’m going to assume the former, and not go into the latter, even though it’s what I’m probably going to do since I think their popup looks like toasted a$$.

6) Next we’re going to find your list’s groups. You might be able to skip this step if you already know the name of your grouping and groups, because the API also supports adding by name, but I think this is a better way because a) you can use the ID, and b) you are sure to use the right strings, because you’ll be copy/pasting them out of the JSON. I actually had to perform this step because I’m not the MailChimp admin, I just have access to an API key.

6.a) First, set up the object you’re going to be calling this code from as a <ChimpKitDelegate> in your header, and #import "ChimpKit.h" in the source file.

6.b) Then implement the chimpkit delegate methods:

#pragma mark - chimpkit delegate methods

- (void)ckRequestSucceeded:(ChimpKit *)ckRequest {
NSLog(@"HTTP Status Code: %d", [ckRequest responseStatusCode]);
NSLog(@"Response String: %@", [ckRequest responseString]);
}

- (void)ckRequestFailed:(NSError *)error {
NSLog(@"Response Error: %@", error);
}

6.c) Finally, you’ll need to run the following code to call the MailChimp’s ‘listInterestGroupings‘ API method. Again, you’ll need to define mailChimpListID_. (I just ran this in a ViewController’s viewDidLoad method.)

ChimpKit *ck = [[ChimpKit alloc] initWithDelegate:self
andApiKey:mailChimpAPIKey_];

// get the lists
// [ck callApiMethod:@"lists" withParams:nil];

// get the list groups
NSMutableDictionary *params = [NSMutableDictionary dictionary];
[params setValue:mailChimpListID_ forKey:@"id"];
[ck callApiMethod:@"listInterestGroupings" withParams:params];

(There’s your example in there of how to get the lists.)

With any luck, you’ll get a response that is a big block of JSON. Use your favorite online JSON parser to turn that into something readable, and it’ll probably look something like this:

[
{
"id":9501,
"name":"Web Signups",
"form_field":"hidden",
"display_order":"0",
"groups":[
{
"bit":"1",
"name":"likes chess",
"display_order":"1",
"subscribers":0
},
{
"bit":"2",
"name":"likes go",
"display_order":"2",
"subscribers":0
},
{
"bit":"4",
"name":"likes puzzle games",
"display_order":"3",
"subscribers":0
}]
}
]

7) Add your group subscriptions by modifying SubscribeAlertView.m around line 140 to look like the following:

NSMutableDictionary *params = [NSMutableDictionary dictionary];
[params setValue:self.listId forKey:@"id"];
[params setValue:self.textField.text forKey:@"email_address"];
[params setValue:@"true" forKey:@"double_optin"];
[params setValue:@"true" forKey:@"update_existing"];
NSMutableDictionary *mergeVars = [NSMutableDictionary dictionary];
[mergeVars setValue:
[NSArray arrayWithObjects:
[NSDictionary dictionaryWithObjectsAndKeys:
@"9501", @"id",
@"likes go, likes puzzle games", @"groups",
nil],
nil]
forKey:@"GROUPINGS"];
[params setValue:mergeVars forKey:@"merge_vars"];
[self.chimpKit callApiMethod:@"listSubscribe" withParams:params];

You’ll also note that double_optin was set to false by default. That’s a stupid default, IMHO.

So there you have it. I think you could probably replace the @"9501", @"id" key/value pair with @"Web Signups", @"name", according to the API docs, but I only tried the ID. I also added some code to the SubscribeAlertView‘s requestCompleted:(ChimpKit *)request method to actually let me know that the submission was successful, but other than that, I think I’ve outlined everything pretty well. Let me know if you find this useful.

Oh, and so life happens and it’s July and Oppo-Citrus isn’t out yet. It’s still “right around the corner”, but as you can see I’ve started this exciting (no really!) freelance project. I was definitely hoping this would happen when I set out on my own, and it’s been going great! It’s 20 hours a week of my time, and it turns out that’s actually more than half my time as an indie. (I don’t think it’s because I’m not working 40 hours either, I think there are just hours you end up “losing” to email or twitter or whatever.) Anyway, last week was a holiday week (the boss gave me two days off!), and I’m planning on slacking some this week too, so I haven’t worked on Oppo-Citrus as much as I’ve wanted. The next goal is to get it at least submitted to apple before I leave for vacation the last week of this month. We shall see. We shall see.

App Store Submission Process using Unity or UDK

I responded to a mobile twin cities thread about developing for iPhone without owning a Mac with the assertion that you still needed a mac to submit to the app store with either Unity or the Unreal Development Kit. It bugged me that I hadn’t verified the information, so a couple of quick google searches later, and I confirmed that I had been correct. Both the unity submission process and submission process for the UDK require an apple machine at some point for code signing.