Dec 23

Accessibility Zoom
Accessibility is one of those areas that most software engineers and product teams seem to have little or no knowledge of. When it is brought to the attention of the decision makers, I’ve heard all too often, “We’ll do that if we have time at the end of the project” or, “What is that? Why do I care about it?” What’s worse, is that in the eyes of many companies and project leads, they can easily rationalize to themselves why accessibility shouldn’t be included in the development cycle:

“Why would a blind person own a touch screen device?”

“I think you’re solving a problem that doesn’t exist.”

“That’s not our target demographic.”

“I can’t see how this would improve our App Store ratings.”

“QA doesn’t know how to test it.”

It’s really sad. Especially when Apple has made it so incredibly simple for us to implement. They’ve done all they heavy lifting for us and simply said, “Carry the baton across the finish line. Please.” And most of us drop the baton.

Honestly, it takes minutes to make your application accessible to a population that all too often gets the shaft. I am a fan of Matt Gemmell. Everything from his tweets to his blog. Even if you’re not a fan, I implore you to read just one article. It’ll make you a better software engineer, and you’ll make your software usable to an audience that seems to lack a voice.

See Matt Legend Gemmell’s article:
http://mattgemmell.com/2010/12/19/accessibility-for-iphone-and-ipad-apps

John Gruber of Daring Fireball quoted this article as:

Must-read for developers. Both a good high-level overview of what accessibility really means and who it helps, and a technical overview of how iOS developers can take advantage of it. iOS is simply leaps and bounds ahead of the competition in accessibility.

Written by Terry Blanchard \\ tags: , , , , ,

Dec 22

Multithreading
Everyone has their own vision of how things should work. As you gain more experience in your craft, you become more grizzled. Well learned. After some time, you earn the privledge of passing this experinece on. Oscar Wilde said it best:

Experience is simply the name we give our mistakes.

Multi-threading in software engineering has been around for a long time. Many mistakes have been made, thankfully. From those mistakes, experience was born. Most of the engineering books talk about the essentials, and the dangers that must be respected and adhered to. But while they talk about the pitfalls of what could happen, none of them really give you great guidelines. I’ve been doing this a long time and I’ve worked with people who should not have made some of the mistakes I’ve witnessed.

Are they bad engineers?
No.

Was there a fundamental misunderstanding about multi-threading?
No.

But there are some fantastic guidelines that aren’t well-established. It seems like Brent Simmons and I agree on a lot of the same principles. He’s written a great blog post about Cocoa Threading that every Cocoa developer should read and understand. He refers to his post as his, “barely-organized thoughts on threading and Cocoa applications” but it covers the points in a concise manner.

Thread Communication Exclusively on the Main Thread

First up is his philosophy on all communication between threads taking place on the main thread. He extends this to notifications as well. I’ll add one more to that list which is KVO notifications. This is essential because UIKit and Core Data don’t like operating on secondary threads. I don’t know how many times I’ve seen

NSAssert( [NSThread isMainThread], @"This needs to run in the main thread" );

 go off because I received a notification or call from a secondary thread.

Communication between systems always happens on the main thread. (A system is one or more objects that work together.) In most cases, communication between objects in the same system happens on the main thread too.

If an object does something in the background, that is that object’s business and nobody else’s.

This extends to notifications: from background threads, I always make sure notifications get posted on the main thread. This way every notification observer can always assume that it’s getting called on the main thread.

Regarding KVO, Brent has this to say:

KVO is a trickier thing. Here’s how I handle that: anything happening in a background thread is not observable (by convention). Whatever is going on is private. When it’s time to set public stuff, stuff that could be observed, those things are set on the main thread.

Threading Methods

There’s almost as many different ways to spin off a thread as there are people in the United States. Brent and I also agree on which methods we use:

I’m very deliberate about my threading. I like Grand Central Dispatch, but for my purposes NSOperationQueue works best. The formal, easily-monitored approach of NSOperationQueue works best here. I definitely recommend against anything but GCD and NSOperationQueue — anything else (NSThread’s detach method, etc.) is too random. (Yes, we used it for years, but we have better stuff now.) (In fact, I almost never even use NSInvocationOperation — I much prefer the structure and defined stop/start of NSOperation.)

I use an NSOperation subclass that takes a target and selector in its init method. When it’s finished, it calls the target and selector on the main thread. This way the caller only ever sees the main thread — it creates the operation on the main thread, then gets called back on the main thread. The fact that the operation happens in the background is unknown to the caller: the caller just knows that it’s async, and doesn’t know anything else.

I almost exclusively use NSOperation subclasses with NSOperationQueue in my applications for the same reasons that Brent outlines. You can create multiple NSOperationQueue’s if you need different operating parameters (for example, one queue that is sequential, another queue that can operate concurrently). Making dependencies between various NSOperation’s is as simple as making an addDependency call. Plus, they can have dependencies across different NSOperationQueue’s.

Locking

NSCache seems to have suffered from poor marketing. It’s a little gem that very few people seem to know about. I’ll bet most of you have written your own class that performs much of the same functionality. I’ll take the very-well tested and used NSCache, which is also thread-safe, any day.

Locking sucks. If you have to do it, you have to do it. It doesn’t mean you’ve failed — failure would be not-locking when you really do need a lock.

There are a couple other things you can do which make sense.

  1. Use performSelectorOnMainThread to set some data that would otherwise require locking. (This is not a trick to use willy-nilly, though — typically it comes at the very end of an operation, not sprinkled throughout.)
  2. Use NSCache — it’s thread-safe.

I highly recommend you read Brent’s full article, “Some Notes on Threading” over at his site.

Written by Terry Blanchard \\ tags: , , , , , , , , , ,

Sep 21

As I write this, I’ve been working on an iPhone application that is very reliant on Internet connectivity. One of the challenges I encountered early in the development of this application was debugging the HTTP requests I was making and the responses I was getting back from the server. One of the requirements is that all communication was performed over HTTPS which clouded my debugging even further.

Meet Chuck, or Charles as the more formal and official name goes. Chuck is my new best friend. Yup, we’re so close that I can call him Chuck. We’re tight.

Charles is a web proxy, HTTP Proxy, and HTTP Monitor that runs on your Mac. Your web browser (or any other Internet application) is then configured to access the Internet through Charles, and Charles is then able to record and display all of the data that is sent and received.

In Web and Internet development you are unable to see what is being sent and received between your web browser / client and the server. Without this visibility it is difficult and time-consuming to determine exactly where the fault is. Charles makes it easy to see what is happening, so you can quickly diagnose and fix problems.

This is great for running your application on the iPhone simulator on your Mac. You can download a free-trial, but trust me on this, you’ll be buying the full version for $50 and thanking me later.

I was curious to know how some of the competing applications worked. While I can build and run my application in the iPhone simulator and use Charles to debug it, I couldn’t help but long for that same insight into other competing applications that I had on my actual iPhone.

Was there some way to have Charles work with my physical iPhone instead of the simulator so I could monitor it’s HTTP traffic?

Oh, hells yes!

It’s actually very easy to configure. Here’s all that you need to make this happen:

  • Your Mac with Charles installed and running
  • Your iPhone with the applications you’d like to monitor
  • Both your iPhone and Mac with Charles must both be on the same WiFi network

That’s it! Got that? Good, let’s configure it. First, we’ll configure Charles:

  1. From the Help menu, choose Install Charles CA SSL Certificate… This will allow you to debug and monitor HTTPS traffic.
  2. If you are debugging or monitoring an SSL connection (or HTTPS request), you will need to configure this in Charles. From the Proxy menu, choose Client SSL Certificates…
  3. Charles SSL Certificates Configuration

  4. Ensure that Enable SSL Proxying is selected. One of the great things about Charles is that you can use wildcards when choosing what SSL sites you would like to monitor. In the above screenshot, I am monitoring all HTTPS traffic on any .com domain.
  5. Run the Network Utility application and make note of your AirPort wireless IP address:

Network Utility IP Address

Now that your Mac is setup with Charles and the HTTP proxy, we need to configure your iPhone to use that Mac as it’s Web Proxy. But first, we need to install the Charles CA certificate on your iPhone.

  1. Open up Safari and navigate to (iOS 4) http://charlesproxy.com/charles.crt or (iOS 3) http://charlesproxy/iphoneconf. When you are prompted to install the Charles certificate, tap on the Install button.
  2. iPhone Install CharlesCA Certificate

  3. Open up your iPhone Settings application and tap on Wi-Fi settings. Tap on the blue disclosure indicator of your local Wi-Fi network
  4. iPhone Disclosure Indicator Network Settings

  5. Scroll down to the bottom of your Wi-Fi settings and tap on the Manual segment control in the HTTP Proxy settings.
  6. Enter in the IP address you wrote down from your Mac running Charles. In my case, when I ran Network Utility I had the AirPort IP address of 10.0.1.33. I put that IP address in my proxy settings as well as the default port Charles runs on, 8888:
  7. iPhone Charles Proxy Setup

  8. To verify your settings, open up Safari on your iPhone. As soon as you make an Internet request, Charles will prompt you on your Mac with a mesage box like the following. You want to click on the Allow button.
  9. Charles Proxy Allow

That’s it! Now fire up that application you’ve always wondered about.

Written by Terry Blanchard \\ tags: , , , , , , ,

Sep 01

“How can we automate our build number in this project? Perhaps a python or AppleScript?”

I get this question a lot. I contract out my development services to companies who need Mac, iPhone, or iPad software designed and developed. Many of these companies have lots of Windows developers on board full-time and contract out their Mac work so I understand that all-things Mac are new to them.

But this question always comes up. Always.

While they’re already thinking about some elaborate scripts to automate this process, I hold up my hands and say, “It’s already covered.”

I decided to blog about it because most people don’t know the name of the tool and can’t “Google” for it without stumbling across scripts to accomplish this task.

Apple includes a command-line tool called agvtool which handles my versioning needs. It’s not perfect, but it does what it needs to do and when used in a corporate environment with a build system, it’s fantastic.

What is it? In a nut shell, it’s a very focused “Find and Replace in Files” command-line tool. It searches through your program’s Info.plist file as well as the project .pbxproj file and updates them. You can even have it commit it’s changes with version control if you’re using Subversion or CVS.

The real number that needs to be constantly updated is the build number. Normally, the marketing version only changes at the beginning of a new branch or feature set. agvtool will help you out with both tasks. First, let’s tackle getting your project setup so you can display the following string in your iPhone About screen:

Version: 1.0 (Build 1)

The agvtool refers to the “1.0″ part as the “marketing version” and “1″ in the Build parenthesis as the project version. To update the build number we simply issue the following command from the project’s root directory which contains the .pbxproj and Info.plist files


agvtool bump -all

This command will change all of the build numbers, or project versions in agvtool speak, to:

Version: 1.0 (Build 2)

Want to change the marketing version to 1.1?


agvtool new-marketing-version "1.1"

Now our About box says:

Version: 1.1 (Build 2)

Cool, huh? Okay, so here’s how you setup your project to take advantage of this nifty little tool. First, we have to tell Xcode that we want to use agvtool for our versioning needs. From the Project menu, select Edit Project Settings. Ensure Configuration is set to All Configurations and Show is set to All Settings. Navigate down to the Versioning section and make the following changes:

Project Versioning Settings

Lastly, we need to update the Info.plist file. You need to set two values in, your Marketing Version is the Bundle versions string, short. If you don’t have this option in your plist file, select an item in the list and click on the + off to the far right. You can then select it from the list. The Bundle version is the build number. Set this value to match the one you placed in the Project Settings option for Current Project Version.

Versioning Plist Settings

Now, whenever you’re ready to build an official release, just run:


agvtool -usesvn bump -all

The -usesvn parameter is optional. For an official build, you’ll want to commit the files that were changed by agvtool.

Then call xcodebuild.

Earlier in the article I mentioned that agvtool isn’t perfect. Here’s what I mean by that comment. For an automated build, having a command-line tool is fantastic. However, if you run agvtool while you have the project open in Xcode, you get this:

Project Has Changed. Read From Disk?

Since agvtool went and changed the .pbxproj file while you had it open in Xcode, you get this. Simply click on “Read From Disk” and you’re back in business. More of an annoyance than a show-stopper.

Written by Terry Blanchard \\ tags: , , ,

Jun 21

I hit a really odd bug last night. I mean, really, really odd. One of those bugs that keeps you up until 4am and you go to bed defeated. I came into the office today and had another engineer sit with me as I went through my code explaining what I was doing hoping that a second set eyes and another brain could bring some clarity.

No luck.

Everything looked good, but this very odd crash was still occurring. We were both scratching our heads. The weird part was that the program ran perfectly on the iPhone and in the simulator, as long as I didn’t have the debugger attached. The other engineer tried the build on his machine and everything worked as it should and he was able to run the Xcode debugger.

I decided to completely remove and reinstall Xcode and the iPhone SDK. Normally, you just drag a Mac application to the Trash Can and you’re good. Xcode is a little different. There’s a ton of different folders, tools, SDKs, simulators, etc scattered around the Hard Drive.

So how do you remove everything?

Fire up Terminal and type:

sudo /Developer/Library/uninstall-devtools -mode=all

Type in your password and go grab a coffee. The Uninstall process takes quite a bit of time as it analyzes every package on your machine. However, it will find and remove all Xcode and iPhone SDK components. I highly recommend you to restart your Mac before re-installing Xcode.

Written by Terry Blanchard \\ tags: , , , ,