A Quick Look At AppCode 2.0

JetBrains recently released version 2.0 of their fantastic Objective-C IDE, AppCode. If you aren’t using it, you should go grab a copy – you won’t regret it. Let’s have a quick look at some of the cool new stuff, and how it compares to AppCode 1.x as well as Xcode.

First Launch

Let’s get to know AppCode! It’s a little bit slow to launch, but Xcode itself is no speed demon here, so it’s hard to fault AppCode too much.

AppCode

Unfortunately, opening a project for the first time still takes a while, thanks to the index building process.

Loading Project

Fortunately, the index building process only seems to happen once per project. Subsequent opens only take a few seconds of ‘Reading Index’. Additionally, there’s no longer a long delay when switching between configurations (iPhone simulator to iOS Device, for example). Thanks, JetBrains! That was a pretty big annoyance.

Look And Feel

AppCode looks a bit different than your typical Mac app. This is understandable, as it’s built on JetBrains’ cross-platform IDE framework – the same Java-based framework that powers products like IntelliJ IDEA and RubyMine.

AppCode

Version 2.0 adds an attractive new dark theme. It’s easy on the eyes, but it’s even more of a contrast from the rest of your system.

AppCode Dark

Keyboard Shortcuts

One of the best things about AppCode is it’s keyboard shortcut support. It includes a built-in Visual Studio keybinding scheme. If you are a developer coming from the Windows world, a nearly-complete set of Visual Studio keybindings is almost worth the price of admission by itself.

AppCode Keybindings

In addition, AppCode supports chorded hotkeys – hotkeys with multiple steps. Instead of having to use hand-contorting shortcuts like Cmd-Shift-Option-Space-R-7, you can use much nicer multi-step hotkeys like Ctrl-R, Ctrl-V to launch the Extract Variable refactoring.

You also get a few other niceties like proper (from a Visual Studio perspective) Ctrl-Tab document switching.

Unit Testing

When you run unit tests in Xcode (and by run unit tests, I mean run all the unit tests in your project, because that’s about all Xcode lets you do by default), an instance of the iOS Simulator gets launched, and your tests are run inside of it. Want to run something other than all the tests in your project? You can either create separate targets for each set of tests you want to run, or find a third party test runner.

When you run unit tests (or a single test, or a file’s worth of tests – it’s nice to have options!) in AppCode, the simulator isn’t used at all. Whatever AppCode is doing, it’s doing it a whole lot more efficiently than Xcode.

Refactoring

Here’s a quick look at some of the refactorings offered by Xcode.

Xcode Refactorings

… and here’s what AppCode has to offer. Quite a difference. I won’t go into the details of all the different refactorings here, but suffice it to say, if you want to do any serious refactoring you should be using AppCode.

AppCode Refactorings

What’s Missing?

In general, AppCode 2.0 is a fantastic IDE. However, there are a couple of important functionality gaps to be aware of.

AppCode does not include a UI designer or storyboard editor. If you try to open up a storyboard in AppCode, it will be launched in Xcode instead. Likewise, AppCode does not include a Core Data model editor, and opening an xcdatamodel will also launch it in Xcode.

AppCode also doesn’t have the ability to submit apps to the App Store. Given the secure, proprietary nature of the App Store submission process, I’m not holding my breath for this feature to appear anytime soon.

On the bright side, the integration between the two IDEs is fairly seamless, and changes made in Xcode are picked up right away in AppCode. I look forward to the day that I no longer have to launch Xcode at all (aside from app submission), but until then, the AppCode/Xcode combo works pretty well.

In Summary

AppCode 2.0 is a great update to an already great product. If you aren’t already using it, you should definitely give it a shot. The raw editing, navigation, and refactoring capabilities are almost guaranteed to increase your productivity, especially if you aren’t a heavy user of storyboards or Core Data.

I honestly wish I had started using AppCode a long time ago; I would probably have a few more apps in the App Store by now. It’s a particularly fantastic tool for UI-less libraries like ios-queryable.

As you can tell, I’m a huge fan of AppCode. But what do you think? Are you more productive in Xcode?

Apple: The Cutting Edge of Software Development

Ok, I know I’m late to the Xcode 4.6 party, but I found this line from the changelog pretty amusing. You might want to have a seat, because this new feature will blow you away:

  • The elements of NSArray and NSDictionary objects can now be inspected in the Xcode debugger.

Yes, that’s right folks. You can now view the contents of arrays in the debugger.

Thanks Apple!

Announcing Surveylitics.com – Create Surveys via Email

Some of you may have noticed that the flow of posts (and apps) has slowed down a bit. That’s because, among other things, I’ve been busy working on a little side project.

I am extremely happy to announce that that side project is now ready for public consumption, so go check it out at http://surveylitics.com!

surveylitics

Surveylitics is a SaaS app for creating online surveys. It’s main selling point is the ability to create surveys via email. Feel free to try it out and send along your thoughts – feedback is always appreciated.

Now that the Surveylitics launch is out of the way, I’ll hopefully be able to spend a bit more time on the iOS side of things. I’ve already got a nifty new app in the works, and a few other ideas in the pipeline.

Nested push animation can result in corrupted navigation bar

While updating one of my apps a while back, I suddenly started receiving a bizzare error message:

nested push animation can result in corrupted navigation bar

Like most iOS error messages, this one doesn’t really tell you anything about what the problem is or how to fix it. Nested push animation? Huh? Am I somehow calling push from within a call to push? Does ‘can result in’ really mean ‘results in’? Why should I care?

It turns out that the problem was quite simple, and was indeed my own fault. I had a segue hooked up in my storyboard… but I happened to have added some code that was manually calling pushViewController. Removing the old segue from the storyboard solved the problem.

Whoops!

Calculating averages and sums using Core Data

Core Data has built-in support for a number of different functions – which it calls expressions – including average, sum, min, and max.

Let’s have a look at how easy it is to use them.

Suppose we have an entity called ‘Product’, and we want to retrieve the average price of all products that are currently in stock. We start off by creating our typical NSFetchRequest object.

NSFetchRequest* request = [[NSFetchRequest alloc] init];
request.entity = [NSEntityDescription entityForName:@"Product"
                             inManagedObjectContext:myContext];

We the set up our filter, to make sure we only retrieve items that are in stock. Obviously a real application would likely have a much more complicated predicated here; this is just for demonstration purposes.

request.predicate = [NSPredicate 
             predicateWithFormat:@"StockStatus = %@", @"InStock"];

Next, we have to specify what type of results we want to be returned. The documentation for this property doesn’t seem to be all that good, so we’ll just do what Apple says and ask for a dictionary.

request.resultType = NSDictionaryResultType;

Now we’re on to the actual average calculation code. We need to create a NSExpressionDescription as the top-level thingy that we are requesting the average with. We give it a name so that we can read it out of the dictionary that we get back.

NSExpressionDescription* averageExpressionDescription =
        [[NSExpressionDescription alloc] init];
[averageExpressionDescription setName:@"thisIsTheAverageThatIWant"];

Here’s where it gets a little strange. We have to give our expression description an NSExpression which specifies that we want the average (this is where’ you’d stick in “sum”, “max”, etc. if you wanted them instead). Then, we have to give that expression an NSExpression to specify what field we want to calculate the average on.

[averageExpressionDescription
    setExpression:[NSExpression expressionForFunction:@"average:"
                                            arguments:[NSArray arrayWithObject:
[NSExpression expressionForKeyPath:@"Price"]]]];

The last thing we have to do to our expression description is set the return data type. In this case, our field is a float, so we’ll specify NSFloatAttributeType.

[averageExpressionDescription setExpressionResultType:NSFloatAttributeType];

We then tell our original fetch request that we want to fetch the average object that we just created.

request.propertiesToFetch = [NSArray arrayWithObject:averageExpressionDescription ;

Finally, we’re ready to execute our fetch request!

NSArray* results = [myContext executeFetchRequest:request error:nil];

Remember how we specified that we wanted a dictionary above? That dictionary is inside the results array, so we’ll extract it, and then read out the value using the key that we specified earlier.

NSDictionary* fetchResultsDictionary = [results objectAtIndex:0];
double finallyIHaveTheAverage = [[fetchResultsDictionary
                objectForKey:@"thisIsTheAverageThatIWant"] floatValue];

And that’s all there is to it! You are now ready to go calculate averages and sums with this simple 17 step proces!


Alternately, you could just use ios-queryable, and do it in one line:

double wowThatWasEasy = [[[myContext ofType:@"Product"]
                                      where:@"StockStatus = %@", @"InStock"]
                                    average:@"Price"];

JavaScript string literals and </script> tags don’t mix

What do you think happens if you try to open up a web page containing the following HTML and JavaScript? Give it a try – the results may surprise you!

<script type="text/javascript">
var x = "</script>";
</script>

It turns out that web browsers are very indiscriminate when parsing closing script tags. The browser will find the </script> tag, even though it’s inside of a string literal in a <script> tag, and consider it to be the end of the script. The result is a few leftover characters and an unmatched </script> tag, which the browser chokes on.

";
</script>

Chrome throws an “Uncaught SyntaxError: Unexpected token ILLEGAL” error.

This was definitely not the behavior I was expecting. After thinking about it, though, it makes perfect sense. The HTML parser doesn’t know anything about the contents of the script. It doesn’t understand that quoted strings should be treated differently. And why should it? The stuff inside the script tags could be anything, in theory.

Sure, this isn’t iOS-specific, but I thought it was interesting enough to be worth sharing anyway.