Amidst the flurry of trolls and meaningful comments about the rather drastic changes from Xcode 3 to 4, I’d like to sum up a few of the major discussions out there, and add a couple of my own remarks
First things first: a word of caution
This is not and should not be about simply changing habits. Yes it sucks to have to re-learn something you’ve used daily for nearly a decade, especially if it means wasting time you need to earn a living. But in the business of making software, we convince potential customers of much much worse. So if your main gripe about Xcode 4 is “dude, I used to do this like that and they are forcing me to do it differently” but the end-result is the same, please abstain from commenting.
Xcode is the only way to make iPhone/iPad/Mac applications. Yeah yeah yeah, you can have makefiles instead, in the same way I can run my car with whiskey: it works, but it borks pretty much everything and might end up blowing the whole thing apart. Unless you are Apple and know exactly the side effects of your build process, you have to use Xcode.
And of course that’s partly why it stings. As mentioned previously here as well as elsewhere, making an app is more akin to art than science. No one would tell a painter: “make a portrait of me, using only a 4-colors ball pen”. Some restrictions are funny, but they can also be ridiculous. By forcing us developers to adapt to Xcode instead of working out how to adapt to us, Apple is being kind of condescending. They know better than us. But that too is not the object of this post, so just leave it aside as there’s no alternative, and that can’t be a meaningful debate.
The Cardinal Rule: You Shan’t Leave
Apple has put a lot of effort into this: if you’re doing it right (for a given value of right, obviously), everything is done within Xcode: version control, file creation, code/xib/coredata editing, debugging, archiving, publishing to iTunes. There’s only one exception to this: Instruments, for profiling your app, finding leaks etc. I wouldn’t be surprised if there was a technical reason for this, probably permission-related, but I bet they are doing their best to integrate it rapidly. A lot of IDEs work the same way, and it’s not necessarily a bad thing.
I just have a thing against mono-window interfaces, I like all my important files to be open in different editors so that I can switch back and forth rapidly. Putting everything in the same window suggests every file has the same importance, when I just know it’s not the case… And I’ll be damned if I understand the new counterpart system: I used to have a small box in the corner; when I clicked on it, it switched from the .h to the .m and vice versa. Now, I have keyboard shortcuts instead, and most of the time, I get it wrong.
The mono-window allows us to see all the projects we are working on. That’s pretty cool. I’ve been using workspaces for this for a while now, and it’s nice to integrate it into Xcode: my 3 projects for this customer are together and the 2 personal ones are in another workspace, etc. As a result, the file filter at the bottom becomes really useful: I don’t have to spotlight all my disk to find where in hell I’ve done that gimmicky thing again: since my projects are grouped by customer and/or kind and/or whatever criteria I want, on a day-to-day routine, it’s a lot easier to find what I’m looking for. Swell!
The mono-window has one major drawback though: I’m not always at home on my 27″ screen to write code. And my 13″ laptop screen is way too small to use Xcode comfortably. Editing text can be done, editing a xib with its relevant .h open on the side requires a lot of juggling.
And that brings us to the major side effect of putting everything in the same window: UI editing. Everyone I know agrees it’s the best thing since sliced bread. Good bye Interface Builder! You have your interface in one editor, the relevant .h/.m files in (an)other(s) and the famous ctrl drag (aka the right click drag) works directly on the code. You’ve put a view in there and you forgot to add an outlet? Ctrl drag the view on the .h, and Xcode offers to insert the outlet in the .h (optionally as a property) and puts the standard code for unloading it properly in the .m. You can obviously connect it to an existing outlet, but many-a-time have I forgotten to put it in the .h and now I am saved! Getting used to the sidebar inspector might take a little while, but in the end it’s a success. Unless, of course, I am on my laptop. Never being able to see the whole view you’re designing just sucks.
So, apart from the fact that I don’t like mono-window for personal reasons, it’s pretty much a success on that part. However, since I’m not supposed to leave Xcode for any reason, it would make a lot of sense to have a plugin mechanism. Yes, I’ve been saying that since revision 1.0 of Project Builder. Back in the day, I wanted to use the Metrowerks compiler, which I found vastly superior to GCC (and apparently I was right, since Apple pretty much switched to LLVM, not wholly abandoning GCC, but clearly saying it’s not the best compiler out there). It took some time to figure out a way to hack together an “xml plugin” to add it to the list of available compilers. Or maybe I have a set of data I will embed in the application that I’ve got a different editor for that I’d like to integrate. Or I just want to do geeky things. Any and all professional application should have a plugin mechanism, bar none. Xcode should not be the exception. Because pros have sometimes very specific things they need to do, we need to be able to tweak Xcode to grant us that power. Otherwise, we have to get out of Xcode to get the work done.
The Way Of The Developer: It’s All About Flow
The typical work cycle of a developer usually includes the following steps:
- Pulling the last changes from the revision server
- Making sure everything still works after the pull (that means running and/or debugging)
- Editing code to fix bugs, add new features, or because the customer/boss wants-it-done-dammit
- Testing for regression
- Committing your (working, hopefully) changes to the revision server
- Publishing the result: that includes sending a beta to relevant people, putting your application out there, …
The first step is getting a lot better in Xcode 4. I still can’t figure out why Xcode doesn’t offer me automatically to pull my SVN changes from the server, sometimes, but it kind of works now. I still like to use the terminal for that step, but at least I know I don’t have to force the people I work with to do the same.
I’ll talk about running and debugging a little further down. I promise.
The edition part, provided you have a big screen and have learned to navigate around the iTunes-y interface, is pretty much covered. Of course, I’d like a plugin mechanism to download crash reports and integrate ticket-management right into xcode, but hey… Maybe someday.
For me, the first gripe starts with running/debugging. First of all, I have to select the right scheme AND destination (Remote Tickets in the Simulator, as opposed to the device). This forces me to do some heavy duty gymnastics, especially when the bug I’m working on doesn’t have the same results on the different destinations (I’m looking at YOU iPhone). How many times have my trusty co-workers heard me yell obscenities because for the tenth time today I ran the program in the wrong environment? And they still jump from their seats to this day.
The side-effect is that depending on this root choice, some actions will disappear. I’m running the simulator, everything’s a-ok and I want to push an IPA? Tough luck, I have to switch to the device environment just for that. Tell me something Xcode: why in hell would I want to archive a simulator version? Therefore if I want to archive a binary, it will automatically be for the device. Therefore the menu should always be available as there’s no alternative!
Testing for regression is also a lot harder than it should be. For Pete’s sake, I have different versions of the simulator (one for every iOS device, running every supported OS version), and I have archives of my builds. Why can’t I keep them somewhere and run them for comparison without having to use the SVN/git/whatever branches? That forces me to have at least 2 versions of the same project open at any given time during my tests.
Committing still has its quirks, but all in all it works fine in Xcode. Finally.
And the last part is so ridiculously convoluted that it deserves a chapter of its own.
Publishing An App (aka Russian Roulette)
Let’s be serious for a second. The objective and benefits of publishing an application isn’t the same for the developers and for Apple. Therefore, there can be some goodwill on both sides, but, as developers we don’t work for them and they don’t have that many incentives to work for us either. Therefore, I’ll just go over that whole certificate thing very quickly.
Apple’s business model is that if you want to distribute an application, you do it through them. Period. There can be some leniency here and there, but that’s the bottomline. To ensure that, we are issued temporary permission to run our work on development devices (ours or our beta testers’), through the use of certificates. A “provisioning profile”, or a certificate in more trivial terms, is a combination of 3 permissions:
- You are a certified developer (aka you have paid), therefore you have a right to run your work on devices
- The device is declared in a list of devices authorized to run stuff from you
- The stuff you are running is (at least partly, for identification purposes) declared in a list of stuff you are doing
This mechanism protects Apple from a black market of applications that wouldn’t go through them.
There are two major types of provisioning profiles: testing/development ones and distribution ones. Development profiles can be used to test your software on devices. Therefore, you are only authorized a limited amount of test devices. Distribution ones are unlimited in devices, and can be issued for the App Store (distribution by Apple) or for Enterprise distribution (a more expensive and legally binding contract).
In my work, there are 3 typical scenarios:
- I work on a personal project that will be released to the general public (via the AppStore)
- I work on a project for a company that will publish the result on the AppStore
- I work on a project for in-house deployment
In Xcode, in the project settings, you set the provisioning profile you are going to use, and at the end of a successful build, the application is signed accordingly. Then you’ve got to figure out a way to deploy it.
In the first case, it gets easier with Xcode 4 than Xcode 3: Publishing an application to the AppStore is ridiculously easy nowadays. Just build and archive, Xcode makes sure all the minimum requirements (icon size and so on and so forth) are met, and pushes the new version of your application straight to Apple for evaluation. Since my own test devices are included in pretty much every profile I have on my computer, testing for myself is dead easy, I don’t even have to change the settings: any certificate will do. At distribution time, a popup asks me to confirm the distribution profile I want to use anyway, so why would I do anything about it? Congratulations on a job well done.
Where it gets hairier, is when you have beta testers. To test your software, they need to have given you the ID of their test devices, you need to have included them in a specific profile through a web interface that’s not the best website I’ve seen out there, and you need to make sure to sign your application with this profile and none other. Problem number one: every time you need to add a new beta tester to the list, you need to go through the whole process of creating a new certificate, identical in everything to the previous one but for the list of authorized devices. Then, in the project settings, you need to make sure you’ve selected the new one (which has the same name as the old one, and doesn’t replace it). This is currently one of the major sources of my daily cursing spree (see below). Once all the beta testing has taken place, you’re home free, the rest is a lot easier.
One step more in that direction: working for a different company. They have their own developer identity, on which you might have only limited access. In that scenario, they have to manage the list of test devices, and grant you the right through a delegation mechanism to sign the application through their account. Basically, nothing changes, except the fact you can’t manage anything anymore: when they update the certificates, profiles and the rest… well if they don’t tell you, you’re screwed. Let’s assume for a second they gave you access and are extremely good at communicating that sort of information (that’s a big assumption).
When it’s not your own project, the pressure changes focus: you are not in charge of the timetable anymore. This means that any error that delays the time they get the application installed on their test devices can be a source for major conflicts. And, obviously, if they called in a contract developer, it generally means that they either don’t have the expertise or they don’t want to. Distribution of beta builds, when it could be done via email for your own beta testers becomes a little less diplomatic.
As many of my fellow developers, I have set up a server that distributes my work for me (kind of like the AppStore, in less pretty): On the test device, they click on a link, and it installs the application automatically. When you have one or two projects, you can do this all manually, it’s no big deal. Editing plists, HTML, and making sure the right profile has been selected is not that complicated. When you have ten projects and generate one or two builds for two of these projects each day, it becomes troublesome very fast. Mistakes are made, panic ensues, grief follows not far behind, hence the daily cursing spree (told you).
In Xcode 3, it was rather easy (when you know how, obviously) to automate that process: build the application, sign it with the right profile and certificate, push it onto the server, and add the relevant info to the web page. It can even optionally send an email to the right people for you. I fiddled around with my own build scripts, and with Hudson.
These build scripts (whatever the flavor) need a few things in order to work:
- access to the code (obviously)
- understand the structure of how Xcode generates the application (especially where in relation to the source code)
- access to the provisioning profiles (more tricky if the server is not a Mac OS X machine, and that leaves a huge security hole as the process needs to access files in your home directory. Oh and to Xcode’s internal shenanigans, a profile doesn’t have a name, it has a fricking 60+ characters identifier, another source of potential mayhem)
- access to your keychain (for signing, even bigger security holes as the process either need to be you or to have your personal password)
Fiddling around for a reasonable amount of time will get you set up. Lo and behold, when I commit something to my SVN, the server grabs the source, checks it, compiles it, signs the app, pushes it onto a web server, and sends an email to my customer. Perfect.
Xcode 4 on the other hand has changed all that: from outside of Xcode, you can’t know where the build has been put. It’s in the preferences of the application itself, it has nothing to do with the project anymore. So there’s an extra layer you need to manually add to your projects: putting the build result in a location that is always the same. Basically, you need to emulate Xcode 3’s behavior in Xcode 4. That’s typically a “new feature” that forgets most developers out there don’t work for themselves. And I read here and there that I’m not alone pleading for a return to a more project oriented structure: I have currently on my disk close to 4GB of builds that I know nothing about. Xcode 4 decides to put a bunch of things here and there, and if I trash the project, or revert to an earlier version, or change its name, or whatever project management thing we do on a weekly basis, these files will stay there till the end of times (or till I find the time to guess which is which and trash what I don’t need).
Wrapping Up, Because It’s Long Enough Already
I like a lot of things in Xcode 4 (workspaces, better source control management, UI designing features, and a lot of small features that made me smile the first time I discovered them). Some choices made are time consuming for me (why in hell can’t I lookup a symbol in the documentation without copy/paste???) but not that big of a deal.
To me, the only thing that is really troublesome is that most of the changes between 3 and 4 were made to keep you inside of Xcode. Good bye external scripting, good bye standard automation (recreating the same scheme over and over and over again with just 2 variables changed isn’t the same as having ONE script that adapts to the project), good bye workarounds for certificate/profiles management… And there is still no way to add plugins to integrate into Xcode what I need to do every day.
Xcode 4 is meant for the solo developer that will publish directly to the AppStore, with maybe a couple of beta tests thrown in. Every other type of developer out there will have to find a way to make it work for themselves, on their own. And we will, because we are, after all, in the same trade. That extra effort is not something I really care for, but I accept it.
Feel free to comment.