After a couple of years of Silverlight and WPF/WCF development on .NET I got handed a nice new assignment the other day, along with some shiny new toys. The job is to complete a partially-implemented iPhone/iPod app, which requires coming to terms with a few technologies that are new to me, namely Objective-C, Cocoa Touch, Xcode, and iOS 4 itself. It’s a bit of a dream assignment as far as fun factor goes, and I hope my boss doesn’t read this blog. He’d probably start thinking I should be grateful. And perhaps I should, if not for the project then at least for the Macbook Pro and iPod Touch 4G that came with it. Both are slick little bundles of cool, albeit at premium prices. But who can hate a free loaner? I powered up and dove in.
The learning curve is surprisingly gentle for a developer with a background in C/C++. Yes, Objective-C syntax is whacky, and it is very dated in terms of its support for object-oriented programming. Cocoa Touch is like any other deep class framework/UI toolkit, and will just take awhile to learn. The tools and environment, fortunately, were much less of a hurdle. The Mac is a Unix box deep down; all the old familiar commands work, and what you do through the GUI is intuitive enough. Xcode itself is not utterly alien to anyone who works in an IDE, but it does have more of an Eclipse feel to it, and it has a few gotchas. One of the ones I encountered today involves how project and target settings are organized.
A little background first. There are two ways to test an iOS application during development. You can use the simulator that comes with the SDK, like the one Google ships with their Android SDK. That works great for most things, but eventually you’re going to want to run your code on a device. If you’re developing an app that works with the push notification service eventually comes sooner, because that API and service don’t work with the emulator. One of the differences between the emulator and an actual device is that applications pushed to a device must be signed with a developer certificate, and the device must have a provisioning profile pushed to it. My problem came in the code signing phase.
After you create your developer certificate on the Apple iOS Provisioning Portal, and have it downloaded and installed, you have to tell XCode to use it to sign the linked binary before copying to the device. The likely place to look for this, it seemed to me, was in the project settings, accessible from the XCode Project menu. And indeed that’s where you’ll find it, in the fourth section down, entitled “Code Signing.” In my case, because the code had been worked on by another developer, his certificate was still specified for signing purposes, and wasn’t installed locally for obvious reasons. I changed this setting to my own certificate, and assumed all would be well.
All was not well. When I tried to build I got an error complaining that the compiler couldn’t find the right developer certificate, and there in the error text was the other developer’s name. Now wait a minute here… I went back in to the project settings and scanned them all carefully: no other occurrences of his name in sight. I reinstalled my dev certificate and reprovisioned the device. Still no go. I sent an email out to the guys who had worked on it before, and who responded promptly with a couple of Google search results, but they all dealt with situations where the developer is using the wrong or an invalid cert. I knew mine was valid. I even tried searching for the other dev’s name using Spotlight. Nothing.
Eventually I stumbled on the contents of the project package and realized that the project file was stored inside it as XML. In the XML document I found the XCBuildConfiguration section listing my cert, and the other dev’s. Obviously he was still associated with the project, but how and why? I had looked the project settings over very carefully, and he wasn’t in them. In tracing through the references in the project file I realized that I was associated with a configuration called “PBXProject” whereas he was listed in the section for “PBXNativeTarget.” Resisting an impulse to just edit the damn text file (a couple of hours had gone missing by now) I headed back into XCode, and finally figured it out.
In the XCode “Projects” menu you can click “Edit Project Settings” and make changes to properties of the project as a whole, which is what I had done previously. What I hadn’t understood at the time was the relationship between project settings and target settings in XCode. A little further down in the Project menu you can see “Edit Active Target Settings.” When I clicked that I saw a set of property pages identical to the eye with the settings at the project level, but there in the code signing section was the other guy’s cert, not mine. It turns out that settings for targets are inherited from the project settings, and can then be specialized. Presumably the other guy had manually set this property at the target level. When I changed it to point to my own cert all was well, and I could build and run the app on my device.
The next phase of this project is going to involve rounding out the GUI implementation, so I hope to have some interesting things to say about Obj-C and Cocoa along the way.