Refactoring in Xcode 5

Oliver Jones

Oliver Jones

Technical Director

  • Xcode

I have a confession to make. I’m an AppCode user. I hardly use Xcode at all.

Ok, so if you know me or have seen my Cocoaheads talk/ramble regarding AppCode you probably already know this.

If you’ve never used AppCode before I suggest you take a look at it, and in particular play with its support for refactoring. Some people can’t get past AppCode’s slightly ugly Java based UI, but if you do get to know AppCode’s keyboard shortcuts and power features I think you will agree it is hard to beat as a Cocoa development tool. It makes me a much more productive developer. I feel like some of my fingers have been removed when using Xcode.

But I digress, this post isn’t about AppCode, it is about Xcode. How to get it to act more like AppCode. Err…. I mean, expose Xcode’s (somewhat limited) refactoring abilities in a better way than is the default, and also to learn about the small in number but still useful code navigation shortcuts Xcode has.

Refactoring Keyboard Shortcuts

Xcode has some limited support for global code refactoring. Tucked away in the Edit menu is the Refactor sub-menu. None of the items in this menu have keyboard shortcuts by default which makes them about as useful as a poke in the eye.

Xcode 5 Refactor Menu

We are going to correct this considerable oversight.

You can edit any of Xcode’s keybindings in its Preferences on the Key Bindings tab. Here you can search the list for all the Refactoring items by typing refactor in the search field. Then double click in the Key column to enable the shortcut editor and then press the key combo you want to use. Xcode will tell you if you’ve created a conflict with an existing key binding. Finding a key combo you like that doesn’t have an existing binding, and thus conflict, can involve a bit of trial and error.

Xcode 5 Refactor Menu Key Bindings

What do these refactoring things do?

Apple has some documentation on the refactoring workflows here. It is always a good idea to consult the official documentation. Below I provide a quick synopsis of the main refactoring actions.

  • Rename - Rename should be obvious. It lets you rename methods, classes, etc and have those changes applied across your entire codebase. Think of it as a smart, semantic, find and replace.
  • Extract - Extract gives you the ability to extract a piece of selected code into a new method or function. It will try and smartly determine what parameters and return values to give the new method based on surrounding code.
  • Move Up - These actions allow you to move a method, property or instance variable up to its super class.
  • Move Down - You would think that Move Down would do the inverse of Move Up, and it does, kinda. Unfortunately it only works with instance variables. Which makes it not as useful as Move Up which can also move methods.
  • Encapsulate - Encapsulate is useful for when you want to convert all uses of an instance variable to into accessor methods, thereby encapsulating that instance variable behind those methods.

Once you’ve added key bindings for these refactoring actions I encourage you to experiment with what they do. Try them out on parts of your code. You may discover that you quickly come to rely on some of them in your day-to-day coding activities.

A note about Snapshots

When you first use a refactoring action in Xcode it prompts you to enable Snapshots. I don’t know if anyone has actually clicked the Enable button in the entire history of Xcode. But if you’re worried about Xcode accidentally obliterating your code, it is there if you want to use it. But you use source control right? So that shouldn’t be a problem, right?

Important: One thing to be aware of however if you do not enable snapshots is that Xcode’s support for undoing changes made by a refactoring is a bit limited without a snapshot. Even when you do save a snapshot restoring the snapshot doesn’t always restore your project perfectly. It might leave you with changes you will need to un-stage in your git repo. This is probably most important to remember when performing a rename refactoring on a class or method used widely in your project.

If you do want to enable/disable snapshots for mass edits like refactoring actions you can do so in File -> Project Settings (or File -> Workspace Settings if you’re using a workspace).

Note also that you can create a snapshot at anytime with ^⌘S. Restoring a snapshot doesn’t have a default key binding. It is in the Xcode File menu. You can manage your project’s snapshots in the Xcode Organizer on the Projects tab.

Other Essential Xcode Keyboard Shortcuts

Edit All in Scope

Although Xcode provides a Rename refactoring action. This action, like all the Xcode refactoring actions, has quite a heavy UI. A quicker more constrained way of renaming things like variables is to use Edit All in Scope ^⌘E which is in the Editor menu. This gives you a quick in-line rename action for renaming variables, parameters, methods and the like. It only changes items in the current scope (and file) so it won’t rename methods in the header or usages in other files like the Rename refactoring action does but it is good for quick local scope renames.

Jump to Definition

Another essential keyboard (and mouse) shortcut to know is Jump to Definition ^⌘J When your cursor is on a symbol (method, variable, whatever) you can press this key combo to quickly jump to the definition (or if you are on the definition to the declaration) of that symbol. Very handy.

You can do this with the mouse too, just hold when you click on a symbol in your code.

Open Quickly

Xcode 5 Open Quickly

Probably the most essential keyboard shortcut in your Xcode arsenal is Open Quickly ⇧⌘O. You should be using this keyboard combo all day to quickly jump around your code. You can search for symbols and filenames in this dialog. Also note that you can use abbreviations and partial matching in the open quick search field. So if you have a View Controller subclass named AwesomeViewController in your project you can search for AweVC in Open Quickly and it will be found.

Hopefully you’ve found these Xcode tips and hints from an AppCode user to be useful.