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.

Code for my iPhone Game Programming Talk

When I did the talk last week on iPhone Game Development, I showed some code at the end of the talk written using the Cocos2D framework. In both talks, the tetris portion of the demo was almost (but not quite) finished. I promised I’d post the code on github when it was finished, so here it is, my intro to iPhone Game Development sample project on github.

Tetris is playable, but this code is barely working, to be honest. I haven’t played with it on a device yet, and I know there are cases in the rotatePiece method that haven’t been tested. I’ve got the next piece in the game model, but not showing up in the view. I was going to use Sneaky Input for the controls, but I ended up scrapping it and just using some really simple touch-based control instead.

Someday (hopefully soon-ish), I’ll be writing a blog post titled “how to write tetris in Objective-C using Cocos2D”. I’ll try and clean it up a bit then.

Introduction to iPhone Game Development

I had the pleasure last week of presenting this talk twice, first for the local meetup.com iPhone developer group, and a second time the following Saturday at MinneBar. Here are the slides from the event, embedded for your pleasure:

For the talk, John Hibshire and I also created a spreadsheet listing all the iPhone game frameworks, libraries and SDKs we could find. I’m going to try and keep this data up-to-date, and add any additional projects as I find out about them.

I think my session was recorded, possibly by folks at the Uptake, but I have no idea if that recording is online (as a few others from the event are). If it was, I’ll definitely update this post to link to it, since these slides are pretty useless without my running commentary. There are some nice links in a “Resources” section in the last few slides, so you can enjoy those if nothing else.

UPDATE: I just posted a link to the sample code for this talk on github in a new blog post. The code shows various examples of how to do really basic things in Cocos2D, including using the schedule method to create a game loop, using the CCMenu class, drawing various particle types, and finally, how to write tetris in Objective-C using a Cocos2D texture atlas for the different piece types.

Base SDK versus OS Deployment Target

A few weeks back, I upgraded to Snow Leopard, and noticed I no longer had the option of choosing 2.0 through 2.2.1 as my active SDK. I was starting a new project, and didn’t worry about it, thinking I’d figure it out later.

Well, now it’s later, and I spent the last hour or so figuring this out, so I thought I’d post it here in case someone else finds this helpful.

In the apple dev forums, I found a couple of people suggesting you need to re-install the old versions of the dev tools, then move my Developer directory, and re-install the latest tools. This seems silly, since I still have the “/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS2.2.1.sdk” directory. It’s possible this suggestion is in order to get the old version of the simulator, although I’m not entirely sure why you’d want to have that.

Another helpful commenter said “Base SDK does not set compatibility. It sets your available feature set. The iPhone OS Deployment Target build setting controls compatibility. Set it to 2.0 or 2.2.1 to allow your app to launch on earlier OS versions.” That made much more sense to me, but I couldn’t immediately find the “iPhone OS Deployment Target” setting in my project settings. I did have it though, it just wasn’t showing up for some reason. When I finally searched for IPHONEOS_DEPLOYMENT_TARGET it showed up, and with a handy dropdown full of old SDK versions.