cjoseph.com

My name is Charles, and I'm an iOS developer (Picky, Kobo).
This is my blog of related ramblings.
Opinions are my own (but feel free to share them).

May 14 2013

Apr 1 2013

Assorted Cocoa Pitfalls

Apropos of nothing, here are a handful of simple mistakes I’ve come across over the course of several years of iOS development, as well as some tips for how to avoid them.

Using non-integral coordinates

If an element of your interface looks blurry (such as a UILabel) it’s most likely because its frame is sitting on non-integral coordinates. If you’re multiplying or dividing the frame’s origin or size you should always be wrapping it with a call to roundf (or a similar substitute).

Updating the UI on a background thread

This is really one of the basics, but I’ve found that if you’ve got a label that’s been set up correctly but isn’t showing any text, or a view that’s been un-hidden but still isn’t showing up, it was probably done from a background thread (even if you swear it wasn’t!). That’s now the first thing I check for when I see symptoms like these. dispatch_async it back to the main queue, where it belongs.

Resource filename case-sensitivity

Have an image not showing up on a device when you swear it had been working in the simulator? Check the asset’s filename. The iOS file system is case sensitive, while the iOS Simulator’s isn’t.

Case insensitive string comparisons

My typical usage of NSString’s isEqualToString: is to pass in a string literal as the argument. Like so:

if ([stringVariable isEqualToString:@"Target String"]) {
        //Do stuff!
}

If stringVariable is nil this will still evaluate to false, so it’s easy to get into the habit of not checking for nil when comparing strings. This is all well and good until you need to do a case insensitive comparison.

if ([stringVariable caseInsensitiveCompare:@"Target String"] == NSOrderedSame) {
        //Do stuff!
}

NSOrderedSame is equal to zero, so in the case of stringVariable being nil it will evaluate to true. This bit me once or twice in the past, so now I always make sure to do a nil check when using caseInsensitiveCompare, like so:

if ((stringVariable != nil) && 
    ([stringVariable caseInsensitiveCompare:@"Target String"] == NSOrderedSame)) {
        //Do stuff!
}


This is fairly basic stuff, but I hope that somebody reading this will be learning something new. And if you have any feedback, I’d love to hear from you – you can reach me by email or @lessthanuthink on Twitter.


Dec 26 2012

Oct 10 2012

TestFlight Live, crashing right before your eyes

As I’m sure most iOS developers are aware of, dealing with provisioning profiles and app builds for testers is a pain, and a service like TestFlight1 is essential for running beta testing.

TestFlight Live, introduced earlier this year, gives you a look at real-time usage statistics for your app. So far I’ve only used its basic features:2 new and returning user counts, session times and totals, device and OS statistics3, and live crash reports.

I’ve been using the Live SDK in Picky since version 2.0 and, apart from having the nice user and session statistics, I was able to fix a bug that had caused the app to crash for two of my customers – something I probably wouldn’t have caught with my (and my beta testers’) sets of test data. It’s with these crash reports (all nicely symbolicated) that TestFlight Live really shines.

Based partly on my experiences with the Live SDK in my own app, we decided to include it in the latest Kobo update (5.7.1) and wow, it’s pretty incredible to see this kind of data for an app with such a large user base. I spent most of the day today combing through the last week’s worth of crash logs, and I managed to fix a whopping twenty-five different crashes. These were all pretty crazy edge-cases that our extensive testing just didn’t turn up – but together they had been logged a total of over nine hundred times.

Apart from our many feature additions and behind-the-scenes improvements, I really think this data from TestFlight Live will be a major factor in making our upcoming Kobo 5.8 release our most reliable and best yet. The live crash reporting is a powerful tool, and I highly recommend using it – and it only takes one line of code to get it up and running.


  1. I also hear good things about HockeyApp

  2. You can also add custom checkpoints to track app usage and behaviours, or pop up questions to solicit feedback. 

  3. Honestly, from my experience the device and OS stats seem inaccurate and inconsistent. The rest is all pretty useful, though. 


Aug 17 2012

An Instagram badge of honour

Listening to today’s episode of The Talk Show and hearing Gruber and Michael Lopp discuss app photography reminded me of something from several months ago. I was browsing my Instagram news feed and saw a familiar picture. Mr. Lopp, @rands himself, had bestowed a ‘like’ on my Skiers photo. Trivial? Maybe – but I consider Rands to be at the top of the class when it comes to iPhoneography (along with Rob Sheridan – the two of them are like magnets for my Instagram likes). I took it as a badge of honour, and it’s helped encourage me to push myself with my photos, as cheesy (and pretentious!) as that sounds.


Update: Wow, well this made my day!


Aug 16 2012

Jul 31 2012

Introducing Picky

Earlier today I released a new app – well, sort of. I’ve relaunched Pod+ with a big 2.0 update, now called Picky.

Truth be told, I’ve never been completely satisfied with the name Pod+, or its icon. I settled on the name when I couldn’t come up with anything better, but have always felt it sounded too generic. The name led to a fairly generic icon, further constrained by my limited graphical abilities. I had deemed both to be “good enough”.

This came to a head during this year’s WWDC. The more I spoke to people about my app, the more the name bothered me. I also had a particularly enlightening session with one of Apple’s designers in the User Interface Design Lab, and his feedback and criticism really brought Pod+’s flaws to my attention.

It was the next morning, as I was preparing for an interview (with The Unofficial Apple Weblog) that I came up with a phrase that I thought described the app well: “for people particular about their music”. After letting that sit for the rest of the day, I came up with the name Picky and the idea to rebrand the app. I’ve been given (mostly well deserved) grief over my picky listening habits, and since I had designed Pod+ around my own needs it felt like a good fit.

The idea for the icon came to me almost immediately after the name did. I was speaking to a friend about it and said something like: “Oh, the icon could be a snooty moustachioed face with a monocle. Ooh, and the monocle could be shaped like a music note!”. I was getting pretty fired up about the idea, and when I got back to my hotel room I sketched out some quick doodles on paper. Later that night I spent an hour or two in Acorn working on a digital version, which I showed to a few other developers, and their feedback confirmed to me that the concept had merit. The final version was done by the talented Jeff Coombs, and you can see all three below:

Having fully committed to the relaunch, I took a lot of time to really polish up the UI, rethink some of my design choices, and make some changes under the hood (to improve memory usage and iron out some bugs). 

Later this week I’ll go into detail on the feedback I took away from the Apple Design Lab, and the interface changes I’ve made since, but for now I’ll wrap this up with a pair of before/after shots that really illustrate the changes, as well as the release notes. I’m really proud of the results, which I’d love for you to check out now that Picky is live in the App Store. I’d also like to thank everyone who contributed their time and feedback – it really made a difference.

What’s New:

Pod+ is now Picky! 

• Gave the UI a fresh coat of paint 

• Redesigned the filter controls 

• Loading indicators now show the progress of library caching 

• The ‘Select Songs’ feature has been tweaked and is now known as ‘Picklist’ 

• Added support for Launch Center Pro 

• Lots of bug fixes and performance improvements


Jun 10 2012

Why I love WWDC

WWDC 2012 is upon us and like many, I’m excited. I feel very lucky, as this will be my third consecutive year attending the conference (thank you Kobo!), and tickets have been selling out at increasingly speedy rates. There are many factors that make WWDC such a great experience, and I thought I’d collect my thoughts on them here.

The big keynote is probably the most exciting event of the week, right as it all kicks off. There’s no better environment to hear those announcements in than being in a room packed with a massive crowd that’s just as, if not more, excited than you are. I cannot wait to find out what iOS 6 has in store for us.

The sheer volume of information, delivered straight from the source, also bears mentioning. Sure, you can download the session videos a few weeks later, but how many developers actually dedicate the time to watch many of them outside of the conference? Having such a large block of time set aside to just listen, learn, and focus makes quite the difference.

Then of course there’s the city it all takes place in, San Francisco. Quite possibly the coolest place I’ve spent time in – I can only imagine what it would be like to live and work here.

There’s also the social aspect – the parties and camaraderie are the focus for many attendees, and though I enjoy the latter, I’m generally not too big on parties (though I may try harder this year :)). But hanging out with friends, coworkers, and peers in San Francisco is really, really great. There are so many good dining options…

But ultimately, my favourite thing about WWDC is the feeling you’re left with: inspiration. Spending a week surrounded by people who’re just as passionate as you are about creating great apps really inspires, motivates, and energizes you. It’s a great feeling to take back home with you.



May 21 2012

A little enhancement to Pod+ I made this weekend. A quicker, better way to get context around your currently playing song – just scroll down. :)


Page 1 of 2