Refactoring in Xcode 5
I have a confession to make. I’m an AppCode user. I hardly use Xcode at all.
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.
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.
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 Downwould 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 Upwhich 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
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
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
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.
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
AwesomeViewController in your project you can search for
Open Quickly and it will be found.
Hopefully you’ve found these Xcode tips and hints from an AppCode user to be useful.