One of the main reasons for decreased productivity is wasting time on repetitive tasks. Even more so if we don’t execute them efficiently. That, in turn, causes us to feel unproductive and slow, which leads to being idle. Being idle leads to the dark side. Well, not quite but you get the point.

I’ve often came across developers claiming they want to be more effective in code-writing. Upon asking what’s stopping them, the reply I received was usually the following:

“My IDE is so poorly designed I lose much of my time on mouse travel and clicking while executing common actions. Besides, frequently used buttons are too far apart. It takes two or more seconds to target and hit the desired button.”

So, we’ve defined our problem. And we have a solution. Keyboard shortcuts, or keybinds for short.

Spice up your daily routine

Working on OS X, as on any other system, can be much faster and much more elegant if you’re using keybinds to spice up your everyday clicking routine. You could launch apps in an instant using spotlight (Command[⌘] + Space bar) and entering the desired application name followed by (Return[⏎]). You can cycle through all of your open applications via (Command[⌘] + Tab) or (Shift[⇧] + Command[⌘] + Tab) for backward cycling.

If you have a complex desktop environment set up e.g. you have your image and video editors opened up on desktop 1 and your development tools on desktop 2, it’s often required to cycle between the two. You can achieve this using (Control[⌃] + Left Arrow) and (Control[⌃] + Right Arrow).

Working with XCode

The good people of Apple lent us a hand by defining various XCode shortcuts (which can be found here if you’re interested in a complete list). Also, while in XCode, you have full access to all of the OS X defined shortcuts provided they have not been overwritten from within the XCode itself.

Let’s follow a sample calculator project lifecycle to see how to get the most out of our editor, almost exclusively using keybinds (little or no mouse actions required).

In XCode, a new project is created using (Shift[⇧] + Command[⌘] + N). The project should be created without any errors or warnings, which is good as we’ll need it to be issue-free later on.

Note: During new project creation, you can cycle between project types, application types and buttons using (Tab) or (Shift[⇧] + Tab). (Shift[⇧]) works with most of the keys and represents a backwards action. Also, it is worth mentioning that a shortcut used for new project creation is the same as for e.g. ‘New folder’ option in Finder, ‘New Private Window’ in Safari, ‘New Command’ in Terminal etc. All in all, it’s worth memorizing.

So, we’ve just created a new module called ‘Calculator’ (Command[⌘] + N). At the moment, the module is blank.

As a calculator which does not calculate anything is not particularly useful, we’ve added a few methods to begin with.


- (double)multiplyANumber:(double)aNumber withAnotherNumber:(double)anotherNumber {
    return aNumber * anotherNumber;
}

- (double)divideANumber:(double)aNumber byNumber:(double)anotherNumber {
    return aNumber / anotherNumber;
}

- (double)invertANumber:(double)aNumber {
    return 1.0 / aNumber;
}

- (double)increaseANumber:(double)aNumber {
    return aNumber + 1;
}

- (double)decreaseANumber:(double)aNumber {
    return aNumber - 1;
}

Now that we have our initial methods written down, they can be tested, for instance, by logging the result of their calls from the app delegate. To open up the delegate you can use the quick open option (Shift[⇧] + Command[⌘] + O). You will be presented with a single-line text box which is capable of intelligently deducing (up to a certain degree) a filename from your input. If one would write e.g. ‘apd.m’ it should properly offer you ‘AppDelegate.m’ for selection.

Once opened, we can now find a method called ‘-application:didFinishLaunchingWithOptions:’ using (Control[⌃] + 6). It offers a similarly deductive input box as quick open does, so just input ‘dfla’ and you should get offered ‘-application:didFinishLaunchingWithOptions:’.

Selecting it leads up to a highlighted method name.

Note: Most of the suggestion lists such as those offered from ‘Open quickly…’ and ‘Show Document Items’ can be navigated using (Up Arrow) and (Down Arrow) keys. On a side note, you could search for a method name in a current file using (Command[⌘] + F), or by using (Shift[⇧] + Command[⌘] + F) for a project-wide search. The later approach offers the benefit of regular expressions.

Generally, we dislike long all-should-fit-in-a-single-row method names so we’ve tidied the name up a bit. First, the cursor was positioned at the end of the selection using (Right Arrow). After hitting (Option[⌥] + Left Arrow) three times in a row, it ended up positioned in front of ‘didFinishLaunching…’ part. The previous action followed by a (Return[⏎]) broke a long name into two rows.

The combination of (Option[⌥]) and arrow keys can be quite useful if you need to quickly navigate through words, one word at the time. You could also throw in (Command[⌘]) in the mix with arrow keys which leads you to the beginning of the current line (Command[⌘] + Left Arrow), end of it (Command[⌘] + Right Arrow), the beginning of your current document (Command[⌘] + Up Arrow) or its end (Command[⌘] + Down Arrow).

Note: Going to the beginning or to the end of a selected text works throughout OS X in the same way it does in XCode. That’s also true for creating selections using the arrow keys combined with (Shift[⇧]). In fact, most of the text selection and navigation shortcuts mentioned in the paragraph above work in OS X as well. While navigating longer documents, you can use (Control[⌃] + Up Arrow) or (Control[⌃] + Down Arrow) to scroll one page at the time.

We could go back to code testing now. After importing ‘Calculator.h’ header, we’ve added the following line to our ‘-application:didFinishLaunchingWithOptions:’ method:


NSLog(@"Inversion test: 1 / 3 = %f", [calc invertANumber:3]);

Everything seemed to be ready for our first test run. We’ve hit compile and run (Command[⌘] + R) aaaaaand..nothing. The code failed to compile. We had forgotten to make calculator’s methods publicly available. So we went back to our module using (Control[⌃] + Command[⌘] + Left Arrow) key combination, which opened up previously edited document. Upon opening module’s header file (Control[⌃] + Command[⌘] + Up/Down Arrow) and pasting the following lines into it


- (double)multiplyANumber:(double)aNumber withAnotherNumber:(double)anotherNumber;
- (double)divideANumber:(double)aNumber byNumber:(double)anotherNumber;
- (double)increaseANumber:(double)aNumber;
- (double)decreaseANumber:(double)aNumber;
- (double)invertANumber:(double)aNumber;

we run the project again, and we saw something similar to the text below in our output window:


2014-12-18 10:53:30.897 Test product[52279:696949] Inversion test: 1 / 3 = 0.333333

Note: Some useful shortcuts for target building actions are (Command[⌘] + B) for ‘Build’, (Command[⌘] + R) for ‘Build and Run’ mentioned earlier, (Command[⌘] + .) for stopping current task execution. To clean current target you can use (Shift[⇧] + Command[⌘] + K). Using (Command[⌘] + K) will clear the output console.

Next, we’ve returned to our calculator’s module file and took a look at ‘-multiplyANumber…’, ‘-divideANumber…’ and ‘-invertANumber…’ methods. We could’ve done a better job defining them. All of them did the same thing – multiplication. Division was no more than multiplication by inversion, so we could have written all of them using a single worker method.

We’ve created a method called ‘-multiplicationWorkerForNumbers:and:’ with the following body:


- (double)multiplicationWorkerForNumbers:(double)firstNumber and:(double)secondNumber {
    return firstNumber * secondNumber;
}

Our three methods (mentioned before) were rewritten in a way that they now used this new worker for performing calculations. Here’s the result of transforming them:


- (double)multiplyANumber:(double)aNumber withAnotherNumber:(double)anotherNumber {
    return [self multiplicationWorkerForNumbers:aNumber and:anotherNumber];
}

- (double)divideANumber:(double)aNumber byNumber:(double)anotherNumber {
    return [self multiplicationWorkerForNumbers:aNumber and:1.0 / anotherNumber];
}

- (double)invertANumber:(double)aNumber {
    return [self divideANumber:1.0 byNumber:aNumber];
}

Being thorough, we wanted to double-check all three methods before we run our program. It would’ve be cool if we could’ve cycled between our methods’ lines of interest but, unfortunately, XCode has not had support for bookmarks for some time now. Here’s what we’ve used as a replacement.

We’ve added some random characters after each of the three return statements – as any characters would do, our favorites such as ‘aflk’, ‘afok’ and ‘afka’ were used. What we’ve produced were three soon-to-be compiler errors.

XCode was smart enough to realize the danger and, in turn, marked those lines as problematic labeling them ‘Issues’. Remember the beginning of this text where we said we needed our project to be issue free? The reason was that now we’ve only had three issues (caused deliberately) and all of them were in the same file (as seen in the image below).

compilerErrors

What we’ve ended up here with, was a way to cycle forward and backward through current issue list using (Command[⌘] + ‘) and (Command[⌘] + “). After all of the checks were done and we were satisfied with the outcome of our coding, the troublesome lines were removed and we were all set.

Note: Another useful thing you can do is to return you cursor to the last edited position in the current document. If it’s off-screen, your document will scroll to it automatically. Let’s imagine our module has many features and is quite more complex than it is at the moment. You’re scrolling through it and suddenly remember that there’s just one more thing to add to the place you’ve modified last. Press (Command[⌘] + Z) followed by (Shift[⇧]  + Command[⌘] + Z) to execute undo and redo actions. The document will have no modifications, but you will end up with a cursor positioned at last modification point. Of course, if you know which line to go to exactly, you can use (Command[⌘] + L) followed by a line number.

Just a little more

There are a few more useful shortcut’s I’d like to mention. Let’s say we’ve had the following method defined and wanted to test it by calculating a factorial of a number 3.


- (double)factorialOfANumber:(double)aNumber {
    double decreasedNumber = (aNumber - 1.0);
    if (aNumber > 1.0) {
        return [self factorialOfANumber:decreasedNumber];
    }
    return 1.0;
}

As we all know, the code above should output 6.0 as a result. But, it seems there’s something wrong with it since the result is 1.0.

A good way of figuring out what’s wrong with your code is by placing breakpoints. After placing the cursor at the first line of our newly created method, we put a breakpoint on it using (Command[⌘] + ). The mentioned command toggles breakpoints for the current line. What that means is that if you use it again, it will remove previously set breakpoint from the line in question.

After the careful examination of our code (and a few debugging steps) the problem got isolated. We forgot to multiply the returning value from our ‘if’ statement by ‘aNumber’. A corrected function body can be seen below.


- (double)factorialOfANumber:(double)aNumber {
    double decreasedNumber = (aNumber - 1.0);
    if (aNumber > 1.0) {
        return aNumber * [self factorialOfANumber:decreasedNumber];
    }
    return 1.0;
}

We could’ve removed the breakpoint, but decided to toggle all of the project’s breakpoints instead (Command[⌘] + Y).

It’s usually a good practice not to declare a variable before you really need it. That being said, we’ve moved ‘decreasedNumber’ declaration before the recursive call in the ‘if’ statement. We could’ve done it by cutting and pasting. Instead, we choose to use a fancy shortcut (Option[⌥] + Command[⌘] + ]) which moves current line (or current selection) downwards. Good thing about it is that it also automatically performs indentation if needed. Its counterpart is (Option[⌥] + Command[⌘] + [) which moves line or a selection upwards.

One last thing. It’s often required to rename a variable throughout the scope it’s being used in. (Control[⌃] + Command[⌘] + E) does just that. For instance, it makes it easier for us to replace ‘decreasedNumber’ with ‘aNumberDecreasedByOne’ in the current method only.

factorialOfANumber

A little something about our workspace

tabBarDrawer

When working on a few logically connected modules at the same time, it’s often useful to have more than one tab open. You can quickly open up a new tab (with our current tab’s content) using (Command[⌘] + T). Navigation through tabs is done with combination of (Command[⌘] + [) and (Command[⌘] + ]) for cycling forward and backward. If you want to close a tab, just press (Command[⌘] + W). Be careful though. The later will end up closing your entire project if you have only a single tab open.

Upon creation, a standard workspace has ‘Project Navigator’, ‘Debug Area’ and ‘Utilities’ displayed by default. As we do not need all of these panels open all the time, we can toggle some of them on/off. (Command[⌘] + 0) toggles ‘Navigator’, (Shift[⇧] + Command[⌘] + Y) ‘Debug Area’ and (Option[⌥] + Command[⌘] + 0) is responsible for ‘Utilities’ toggling.

Navigator has a few panels which, in XCode 6.1.1 at least, are: Project, Symbol, Find, Issue, Test, Debug, Breakpoint and Report panels/navigators. Each of them is accessible through keybinds using (Command[⌘] + 1) through (Command[⌘] + 8) respectively.

With our calculator module open, we’ve pressed (Shift[⇧] + Command[⌘] + J) to make XCode mark it in the Project Navigator. This proved to be extremely useful in large projects when we wanted to re-arrange the project structure for example.
Looking at our default project structure, module’s files seemed out of place. Now, there’s no default shortcut set for ‘New Group from Selection’, only for ‘New Group’ which is set to (Option[⌥] + Command[⌘] + N). What I like to do is to swap those two, so ‘New Group’ shortcut actually becomes ‘New Group from Selection’ shortcut.

That allowed us to select both calculator files (module and header), and to create a new group named ‘Calculator’.

Conclusion

Keybinds are not your standard cure-all obviously, but they allow you to execute standard and repetitive tasks faster and easier. While working with text (or source code in our case), they offer a more precise way of word selection, text navigation, etc. Finally, as there’s no need to follow the mouse pointer visually when using keyboard, we can be more focused on the work we do than on how we do it.

A list of mentioned shortcuts

General
Key combinationAction
Shift[⇧] + Command[⌘] + NCreate new project
TabCycle through screen controls
Shift[⇧] + TabCycle through screen controls backwards
Command[⌘] + NCreate new file
Shift[⇧] + Command[⌘] + OOpen file quickly
Command[⌘] + 0Toggle navigator
Shift[⇧] + Command[⌘] + YToggle debug area
Option[⌥] + Command[⌘] + 0Toggle utlities area
Project navigation
Key combinationAction
Command[⌘] + FFind in currently open file
Shift[⇧] + Command[⌘] + FFind in current project/workspace
Command[⌘] + ‘/”Go to next/previous issue
Command[⌘] + LGo to line
Command[⌘] + TOpen a new tab with current tab’s contents
Command[⌘] + [/]Open next/previous tab
Command[⌘] + WClose current tab (window)
Command[⌘] + 1..8Select navigation panels (Project, Symbol, Find, Issue, Test, Debug, Breakpoint, Report)
Shift[⇧] + Command[⌘] + JSelect current file in project navigator
Option[⌥] + Command[⌘] + NCreate new group in project navigator
Code editor
Key combinationAction
Control[⌃] + 6Quickly find a method in currently open file
Option[⌥] + Left/Right ArrowGo to the beginning/end of a current word
Command[⌘] + Left/Right ArrowGo to the beginning/end of a current line
Command[⌘] + Up/Down ArrowGo to the beginning/end of a current file
Control[⌃] + Up/Down ArrowScroll page up/down
Control[⌃] + Command[⌘] + Left/Right ArrowOpen previous/next file in opened file history
Control[⌃] + Command[⌘] + Up/Down ArrowCycle through modules associated files (header, implementation, etc.)
Command[⌘] + ZUndo last action
Shift[⇧] + Command[⌘] + ZRedo last action
Option[⌥] + Command[⌘] + ]/[Move current line down/up
Control[⌃] + Command[⌘] + ERename current entity in scope
Product builder
Key combinationAction
Command[⌘] + BBuild
Command[⌘] + RBuild and run
Command[⌘] + .Stop current task (building, cleaning, etc.)
Shift[⇧] + Command[⌘] + KClean current target
Debugging
Key combinationAction
Command[⌘] + KClear output console
Command[⌘] +Toggle breakpoint on current line
Command[⌘] + YToggle project’s breakpoints
0 comments