(mostly some personal info about me - skip if you're only interested in the comparison):
I've always been an Eclipse fan.
Eclipse was always my favorite IDE for Java, and therefore when I started developing in Python PyDev was the obvious and excellent choice.
I tried a little bit of Jetbrains' IntelliJ and PyCharm. They both seemed very impressive, but to be honest - whole the project settings there were a little bit scary for me, plus they cost money and I was happy with the free Eclipse so I didn't see a good reason to make the move.
Upon joining JoyTunes, I started to develop in 2 new technologies for me: ActionScript3, and Objective-C.
Naturally, Xcode was the first IDE I tried for ObjC. All the tutorials and professional materials are always demonstrated with Xcode so there's no real escape from having to learn it as your first Xcode IDE. I heard about AppCode, but I heard it's very early stage and Xcode was free for apple developers and good enough for a novice iOS developer like me.
ActionScript3 on mac is a different story though. You can't really find any good IDE for that without having to spend a significant amount of money (FDT seems like a decent IDE for that, but the free version is way too limited). Finally stumbled upon Astella.
Astella was such a good experience for me, had pretty much everything I was looking for in an IDE, and even though it's still on beta-testers phase, it's certainly good enough for me and I'm using it as my primary ActionScript development environment.
So, I thought to myself: All JetBrains products are pretty much alike. If I got used to Astella, getting familiar with every other JetBrains product should be pretty much trivial. So why not give AppCode a try?
So I did.
And there you go - the findings!
(if you skipped the boring intro this is where you come in)
Disclaimer: The comparison was made between Xcode 4.2 and AppCode 1.5 EAP - things might change for future versions of both IDEs.
This is going to be long, so I'll tell you who won in each category in the headline, and you can skip the category if you don't care for it too much.
Well, that's a no-brainer. Xcode is free for apple developers, and is sometimes free for non-developers as well (Apple keeps changing that, I lost track), anyhow the highest price I saw for Xcode was 4.99$.
AppCode costs 199$ for commercial license, 99$ for indie developers, and it's free for Open Source projects.
Wondering if it's worth the price? Keep reading :)
I believe most of the readers know the importance of refactoring the code. If they don't - they should look it up or grab a book...
Anyhow, refactoring is something that without the right tools could be very painful and dangerous, so refactoring is definitely one of the first feature to look for in the IDE you choose from.
Xcode has refactoring, but lets examine what it has to offer:
|Xcode: only 6 refactoring methods available|
Create superclass, move up and move down are pretty rare. Encapsulate? You mean for an iVar? Who declares iVars anymore? Just use properties.
The rename refactoring was buggy for me in several cases (forgot to rename some stuff or simply crashed Xcode and left the code in an unstable state), and it doesn't have the option to rename text occurrences as well, which is funny because by default - Xcode writes the name of the file on the top - so renaming a class will always require you to change the filename in comment manually.
Furthermore, notice there are no keyboard shortcuts for refactoring by default (you can configure them, but come on...), and using Refactor -> Rename... from the menu will always open a popup screen with a preview, even when renaming a local variable.
You CAN rename a local variable by selecting the "Edit All In Scope" after hovering over the variable:
|Xcode: Edit All in Scope is in the same menu as "Add to iTunes as a Spoken Track"|
AppCode, on the other hand, is on a complete different level here. And it keeps getting better (some of the refactorings I metion were added in the recent prerelease version of AppCode 1.5 and there are more to come).
This is the current refactoring menu in AppCode:
|AppCode's refactoring options: Aah... That's better!|
Notice that almost every refactoring has a built-in keyboard shortcut by default, and even the ones who don't have one are still easily reachable without using the mouse (I'll discuss keyboard shortcuts later).
Other cool things to mention here, is that the "rename" refactoring is very context aware, and usually can be done "in place" (i.e. without a dialog box).
One really cool dialog box worth mentioning, is the Rename method / Change signature one:
|AppCode's Change Signature dialog: Very well designed|
However, in general - you can see what I mean when I say they're not in the same league here, and AppCode is the definite winner.
Quick Fix (AppCode!!!!)
Quick fix is IMO one of the most important features of an IDE, if not THE most important one.
If you don't know what this feature means - basically it means that when the cursor stands on an error/warning and choose from a menu of things you can do in order to fix the problem.
This is great if you're practicing TDD, or other forms of "Programming by Wishful Thinking" when you type the code you need to use before it even exists, as it can generate the missing methods/classes for you.
Even if you don't do TDD, I think all Objective-C developers would know how annoying it is to declare a @property and have the compiler complain about it not having @synthesize. Well with quick-fix, it becomes a whole lot easier...
Advanced IDEs (such as AppCode) will do even better and let you "quick-fix" stuff that are not even errors yet, like add a missing private declaration for a helper method you have in your .m file, etc.
So, does Xcode have Quick Fix?
It actually does, but it's very basic and limited. In order to use it, you can either click the red dot near the problematic line (if you could ever succeed doing it without adding a breakpoint... so annoying!!), or you can use the keyboard shortcut ⌃⌘' for quick-fixing next error.
|Xcode: lets you fix only trivial things like a semicolon|
AppCode, on the other hand, has extremely powerful quick-fix feature, by simply standing on code and typing Alt+Enter. Instead of describing it in words, here is an example:
|AppCode: Red lightbulbs are fixes for errors, pencils are quick-edit operations you can do|
The cool thing, which brings me back to the refactoring issue, is that all the creation of code is done by the same dialog boxes or in place renaming features of the refactoring operations. One of the coolest quick fixes is this one:
|AppCode 1.5's new property quick-fix : Just type self.something and press Alt+Enter...|
|One click for everything! It evens releases "retain" property in dealloc for you|
Damn, I wanted a private property and it defined it in the interface? What do I do?
You guessed correctly. Alt+Enter again:
|AppCode's Quick-Fix: more powerful than you think...|
Well, I think you get the picture - AppCode's quick-fix is simply magic and saves you precious development time. Xcode? Well... It can fix missing semicolons...
The only thing you need to notice about quick-fix, is that if your code is inside a macro (e.g. STAssertEquals), it sometimes fails to work properly.
BTW, the annoying breakpoint adding instead of showing the error is easily avoided in AppCode. First of all you need to hold your click for about 1 second before it creates a breakpoint, and also the error/warning will appear as a floating lightbulb near the text and not in the beginning of the line.
Code completion & generation (AppCode)
I must say I really enjoyed Xcode code completion when I started with it. It really knows what I'm going to write and it's very easy to choose from the list of suggestions.
AppCode is no sucker here as well and has pretty much the same code completion standards as well. The only annoying thing for me is that sometimes you select the completion you want with Enter and sometimes with Tab (e.g. for suggestions of variable names). But I can live with that.
A place where AppCode has a small win in code generation, is when you need to implement/override a method in an @implementation context.
In Xcode, as I had a hard time finding out at first, you can go into method-name-completion mode by starting a line with '-' and then the name of the method:
|Xcode: type '-' and the beginning of a method name to activate completion|
You need to choose if you want to Override a method (⌃O) or Implement a method (⌃I). And then you get a menu like this:
|AppCode: dialog box instead of text only, but you get to see what you are overriding exactly|
Another aspect of code generation, are common templates like templates for init/dealloc/etc.
In Xcode 4, Apple added the "Code Snippets" feature:
|Xcode's Code Snippets feature: quite neat.|
In AppCode, sadly, simply typing "init" won't do anything. Not because AppCode doesn't have its own snippets mechanism, but because there's another way of generating initializers, which is the "Generate..." feature, activated by ⌘N:
|AppCode's Generate menu - similar to its refactor one|
In conclusion, the difference here is less significant, but AppCode is a little better, because of the more controlled and easier to discover method names completion.
Key Bindings (AppCode)
A little background for this part:
"oh no... background again? I though I skipped this..."
Well tough... Deal with it.
First, I must admit I'm a newcomer to Mac OS X and therefore what seems intuitive to me might be different for some power Mac users that read this review.
Second, I work with a full Mac keyboard with the keypad:
|Full Mac Keyboard: Helps me to be more productive|
Anyhow - sorry for digressing from the comparison - just thought this is good to know and an important tip.
Default key bindings behavior:
So, the good thing about both IDEs regarding key bindings is that they are quite easily configurable, so no matter how crappy you think the default bindings are, you can also customize it to make more sense to you.
Regarding the default key bindings - when starting with Xcode I found myself reconfiguring a bit too much: Page Down/Page Up only scroll the view and not move the cursor, Home/End key goes to the beginning/end of the document, and more...
In AppCode, I can't remember anything I had to configure, and the default bindings worked quite nicely. Regarding Home key specifically - AppCode has an additional feature that pressing home key multiple times will move from the first column in the line to the first non-whitespace character in the line - quite useful. In Xcode I couldn't really find a way of doing this.
A small win for Xcode here, is the Ctrl+Arrow Keys vs. Alt+Arrow Keys (Also Ctrl/Alt+Backspace/Delete): In Xcode using Ctrl+Move jumps to the next/previous CamelHump (notice in Lion you need to disable the default behavior for Ctrl+Left/Right in the System Preferences in order for this to work) and Alt+Move jumps to the next/previous whole word. This is useful, because camel-hump jumpings is neat when you want to change a variable name etc., but if that's your only way of skipping words it could be slowish.
In AppCode, you have only Alt+Left/Right. By default it moves entire words, but you can change this in the preferences (look for "CamelHumps")
Difficulty in learning the key bindings
Here AppCode's win is more noticeable.
Both AppCode and Xcode have the key bindings written near the operations in the menus. However, in AppCode every button you hover on have a key binding written in the tooltip, which isn't the case with Xcode:
|AppCode: tooltips contain the key bindings so you can easily memorize them|
|AppCode's "Find Action..." dialog: turns your IDE into a command line interpreter|
Quick Reference Card
AppCode comes with a built in keymap reference card, that can be reached from the help menu (or by using Find Action of course...)
Xcode doesn't have a built-in one, and I'm afraid that the ones that you can find on the web are usually not up-to-date, since Apple tends to change the key bindings from version to version of Xcode, and not everyone always bother to update the reference cards.
All in all, I find myself using the mouse a lot less in AppCode, since it's easier to learn the shortcuts, and there seems to be more shortcuts in general. If you want to learn the existing shortcuts in Xcode 4+, these screencasts might come in handy.
Project Setup and File Management (Xcode)
Here we are touching the weak spot of JetBrains as I see it. In all of their products, the most unintuitive and cumbersome thing is how do I configure the project - the dependencies, which files are built and how, etc.
I once tried to add an external framework for my project from AppCode, and it caused complete chaos. Files were copied instead of being referenced, stuff didn't compile, and I ended up undoing everything and starting from fresh in Xcode for the dependency to work well.
Furthermore, there are some basic projects settings Xcode has that I simply couldn't find in AppCode. The build settings and various flags is one example, but a common use case is the following:
You have a test target and a regular target. When you add a source file or resource to the project, you need to choose which targets should include it. AppCode lets you choose this when you add the file, but if you want to change it later because you forgot or made a mistake, you must launch Xcode.
|Xcode's project/build settings view. |
You need to mess with it so often, yet AppCode simply doesn't have it.
Something that makes the whole thing less critical when deciding if you want AppCode or not (and is a big win for AppCode), is the fact that AppCode is 100% compatible with Xcode's projects settings and the project.pbxproj file. This means that you can change settings in one IDE without fear and the other will automatically synchronize on the changes.
Another small win for AppCode in this category, is the ability to move from the standard Xcode project structure view, to a regular file-based view:
|AppCode lets you see your project as regular files|
This can be useful when you want to add something to your project that was already copied to the directory.
Also, in Xcode the order of the files in each group matters. Why? I'm really not sure, but all I know is that I end up reordering everything and scrolling stuff around whenever I add a new file and it really annoys me. In AppCode, everything is sorted alphabetically.
Code Inspection (AppCode)
Once you fiddle with the compiler settings of Xcode, you can have it warn you about quite some stuff it doesn't warn you about by default. You can also (and should!) tell it to treat warnings as errors:
|Xcode's warnings section in build settings.|
You can also run "Analyze" for your project in Xcode using ⇧⌘B, which will run the clang tool and find mistakes that are not necessarily something the compiler finds on a regular basis.
These 2 features by Xcode would probably be enough in catching most of the stuff you need. However, AppCode's code inspection feature takes it to the next level:
- Finds unused code (class/method/property) and not only unused local variables.
- Finds unused imports
- Finds spelling typos in comments and in variable names.
- Finds memory management errors (e.g. alloc with no release)
- and many other new inspections...
Inspection is triggered whenever you change a file. But you can run inspection on your entire project (no key binding, you'll have to use "Find Action..."), which gives you a very nice summary of all errors:
|AppCode's inspection view|
You also have a square indicator in the corner of the file you're editing that tells you the overal inspection status of that file:
|AppCode: a green/yellow/red indicator tells you the overal inspection status of the file.|
Inspections are of course configurable via settings.
The only problem with AppCode's advanced inspections system, is that it gives too many false alarms:
- Sometimes the default category for private methods is recognized as an unused interface
- If I release an iVar in tearDown of tests and not in dealloc it warns, you can configure it to warn only if it's not released at all, but it's buggy
Unit Tests Support (AppCode)
If you're reading my blog, you won't be surprised to know that this is one of the most important things I look for in an IDE.
Xcode 4 added built-in support for unit-tests via the OCUnit testing framework. This was quite a big deal for me when I heard about it.
The built-in support means basically that you can add a checkmark to "include unit-tests" when you start a new project, it sets up an additional test target for your project, and then you can run all the tests in the project with ⌘U (you actually need to fiddle with the settings a bit to make it run without launching the simulator, but that's a different topic).
This is how the it looks when you run all your tests:
- You can't really run a specific test, must run them all.
- If you want to look at the logs of a single test (e.g. for debugging a failed test), you must find it in the console manually, as it contains the log for the entire test-suite run.
AppCode solved both problems: it allows you to run a single test (either ctrl+click the function that you want to run or add a new run configuration for a single class), and when a test fail, you can click it and see the log for the failing run:
|AppCode's Test Results View: Green/Red bar + only relevant logs|
Notice you also get a green/red bar instead of a simple popup with test succeeded/failed - good for TDD.
So this is why I think AppCode is better for unit tests.
2 small wins for Xcode though in this category:
- It paints the failing asserts in red in the code:
|Xcode makes it easier to see what assert failed in the code|
- In AppCode, if I have special dependencies for the test target (e.g. OCMock framework), after running my regular target, code inspection will go crazy on me for my tests:
|AppCode: if test target is not the last target I ran, errors are flying all over the tests code|
Git Integration (tie, simplicity vs. robustness)
I must admit I like Xcode's git integration. It's very simplistic and therefore it's easy to use and understand.
Simply type ⌘⌥C and it opens a commit pane with the ability to diff everything and commit when you're done:
|Xcode's commit windows: do everything from one place|
So if you're looking for simplicity, and not afraid to use command line or a different GUI for the more complex git operations, Xcode is the better choice.
However, if you're looking for robustness and doing-everything-from-one-place, AppCode's git integration is better.
|AppCode's Changes view|
First of all, AppCode has other source-control systems supported, like SVN (didn't try them though)
Second, you pretty much get full git support and not simply diff/status/commit like in Xcode. You can stash, annotate, push, rebase, etc.
Finally, the commit window itself is very powerful:
- Unlike Xcode, it saves the previous commit message you entered, even if you cancelled a commit because you remembered you need to add something.
- You can tell it to automatically Optimize Imports, run code inspection, or warn you about TODOs you added (which is good if you regard your TODOs as "TODO before committing") on affected files before committing them
|AppCode's commit dialog - cool "Before Commit" options|
The final parameter that Xcode and AppCode differs by, and there's a small win for AppCode in, is the diff window.
Both IDEs has a full-featured editor in the diff window, which is something I find extremely important and lacking in some other IDEs (like Eclipse for Java).
The reason AppCode wins here, is because you have special keyboard shortcuts for going to the next diff ( F7 ), or to the next file in diff ( ⌘⇧] ).
Disaster Recovery (AppCode)
Local history and snapshots are a very important thing, especially when you lack the "commit often" discipline when working with version-control.
Both have this feature (called Local History in AppCode and snapshots in Xcode).
The difference is that Xcode snapshot are pretty much only if you told it to make them (which is the default for operations like rename or massive replace), and in AppCode they are done by default for every 'git pull', refactor, a run of all the tests or even regular edit:
|AppCode's Local History view: saved my ass in many occasions...|
Run Configurations (tie)
Xcode makes it easier to switch between device/simulator/tests (you simply choose from the schemes menu).
Also, running all the unit tests in the project is always done via ⌘U and you don't need to define it.
AppCode 1.5 improved from its predecesor in this area, but still you need to go through a configuration pane in order to define a new run configuration (on device/on simulator/all tests/...).
However, this needs to be done only once. Once you configure it, you can quickly choose from your configurations using ⌃⌥R (or ⌃⌥D for debug), and that's fun:
|AppCode 1.5's "Run..." Menu: Activated with ⌃⌥R|
Both debuggers are pretty similar. I think AppCode's debugger may have a little more options, but I admit I never found myself using them too much.
The one thing I do like better about Xcode's debugging abilities, is exception handling. This is not the default behavior, but something that is crucial and I did not find a way of achieving in AppCode, is the ability to stop the program before it crashes with an uncaught Exception, and figure out where the exception came from.
In Xcode it is achieved as described in the following screenshot:
|Xcode's exception breakpoint. Could not find this in AppCode|
Auto Line Wrapping and Indentation (Xcode)
Both have pretty good auto-indentations features. Auto indenting a line or block key bindings are ⌃I in Xcode and ⌃⌥I in AppCode.
AppCode's main advantage is that you can tell it to wrap automatically when you pass the right margin.
Xcode's win here is because it simply wraps smarter most of the time (just try and see for yourselves...). I guess it might be configurable in AppCode, but still...
Another cool thing in Xcode is that you can increase or decrease indentation level when your cursor is at the middle of the line, with ⌘] or ⌘[ respectively.
And of course, there's the awful bug in AppCode that causes it to join long method names into one line if you refactor->change signature for them (mentioned earlier).
Miscellaneous Wins for Xcode
- You MUST use Xcode if you want to use interface builder, plist editor, creating an .ipa file, and lots of other features you need during app development cycle.
- Memory consumption is generally lower, and often you need both Xcode and AppCode open so if you have less than 8GB RAM you're in a real trouble running AppCode.
- In Xcode, command+click goes either to the definition or to the declaration of a method, depending on the context. In AppCode it will always go to the declaration (⌘B will also work), and it was harder for me to find the "go to definition" shortcut because it's called "go to implementation", and it's ⌥⌘B, but thanks to an anonymous commenter on this post now I updated this here and everybody knows so it's not so bad :)
- Easier to configure the print margin. In Xcode once you do it it's configured. In AppCode, took me some time to find it, but eventually I figured out that the special color of the print margin was off by default (configurable in the settings, search for "right margin" there).
Miscellaneous Wins for AppCode
- Has an indicator for the column number the cursor is at (a must for any editor if you ask me... Xcode simply doesn't have it).
- I can't really prove it, but seems to crash less often. Especially when switching a lot between running unit-tests to running the app on the device.
- You can easily know if a method is implementing/overriding/doesn't have a declaration:
|AppCode's "Go To..." Icons. |
If there's no icon you know it's not declared anywhere and you should use quick-fix to add it to your private category.
AppCode, like other products from JetBrains, has pretty much everything you expect from a decent IDE and more.
Xcode is no sucker as well, but really lacks when it comes to refactoring, quick-fix, etc.
Also, like other products from JetBrains - all the project structure, dependencies, etc. is very cumbersome. In Xcode it's no picnic as well, but at least everything works eventually.
If you haven't done so, try out AppCode and enjoy it.
Then, start your projects in Xcode - configure everything there, but when you're on a streak of writing a lot of code and not too much messing with project configuration and hardcore debugging - do it in AppCode. Whenever you do an operation that requires some special configuration (such as introducing new frameworks or a new project dependency) - move to Xcode, do the necessary stuff - and go back to AppCode.
Maybe the most important win for AppCode it that it is fully Xcode compatible, meaning that the move between the IDEs is so smooth that I wouldn't worry about at least giving it a try - you can always change your mind and go back and forth to Xcode smoothly.
Liked this post? Great!
Please spread the word, subscribe to my feed and follow me on twitter.
EDIT (updates since writing the post):
- The bug of AppCode removing line wraps when renaming a long method is solvable by configuring it in Settings -> Code Style -> Objective C -> Wrapping and Braces
- Xcode DOES have a Find Action feature, it's the "Search" in the Help menu. Unfortunately - no default key bindings.
- Found something else? Write it in the comments, and I promise to monitor it and keep this post as updated as possible.