Xcode Multi-Cursor Editing

I recently found myself rediscovering Xcode’s multi-cursor support. Here’s a reminder in case you need it.

Last updated: Mar 27, 2023

Column Editing

I’ve never known what to call it, but I think the multi-cursor feature that I use the most starts by holding down the option (⌥) key and dragging to select a column. Here I’ve dragged down with the mouse to select the let keyword on four consecutive lines:

Four lines of Swift code with column of let statements selected

If you don’t want to use the mouse you can select a column above or below the cursor position using the ⌃⇧+Up or ⌃+⇧+Down keys. Now if I type var I replace the let on all four lines in one go:

Four lines of Swift code each with a cursor after var keyword

Note the four cursors positioned at the end of the let. You can move all four cursors with keyboard arrow keys or hit the escape key to get out of multi-cursor mode.

Multi-cursor Editing (Control-Shift-Click)

Multi-cursor editing is not new. Apple added support to Xcode 10 back in 2018. That was apparently a big year for the source editor as Apple published separate release notes:

Here’s what they said about multi-cursor editing:

The Xcode Source Editor now supports multi-cursor editing allowing you to quickly edit multiple ranges of code at once. You can place additional cursors with the mouse via ⌃+⇧+Click or with column select (⌥+Click+Drag), or with the keyboard using ⌃+⇧+Up to column select up or ⌃+⇧+Down to column select down. (12564506)

We’ve already seen the column selection. What I forget exists is that you can ⌃+⇧+Click anywhere to add extra cursors. For example, here’s a SwiftUI view that I moved to a Swift Package where I want to make the methods and properties public:

struct ErrorView: View {
  var error: Error?
  init(error: Error? = nil) { ... }
  var body: some View { ... }
}

Starting with the cursor positioned at the start of the first line (before the s in struct). Using ⌃+⇧+Click I can add extra cursors before the two var properties and the init method:

ErrorView struct with four cursors before properties and methods

Typing public then changes all four places in the source code:

Four lines of Swift code each starting with public and with a cursor visible.

Use ⌃+⇧+Click on a cursor to remove it.

With Copy and Paste

A tip I saw used in the WWDC 2018 State of the Union video is using multiple cursors with copy and paste. For example, here’s an enum I used when experimenting with adaptive stack views:

public enum Condition {
  case compact
  case regular
  case accessible
  case compactAccessible
  case regularAccessible
}

Each of the condition cases has a method with the same name that I want to return from a switch. Xcode code completion fills out the switch for me:

Switch statement with six cases each with a code placeholder

I need to replace each of the code placeholders with a return statement. Back at the enum I can ⌃+⇧+Click to place a cursor at the start of each of the condition names:

Enum with six cases each with a cursor before the value.

Holding the ⇧ key, a ⌘+Right-arrow selects to the end of the line which I can then ⌘+C copy to the clipboard.

Enum with six cases each with the value selected.

Back at the switch statement, I can add cursors at each of the code placeholders and again select to the end of the line with ⇧+⌘+Right-arrow:

Switch statement with six code placeholders selected.

Now I can type return, add a space, then ⌘+V to paste in the condition names. Xcode is smart enough to paste the six lines from the clipboard at each of the six cursor points:

Switch statement with six cases each with a return and visible cursor at the end of line.

To clean things up I can even Up-arrow to move all the cursors up a line and delete the new-line and spacing:

static private func handler(_ condition: Condition) -> ConditionHandler {
  switch condition {
  case .compact: return compact
  case .regular: return regular
  case .accessible: return accessible
  case .compactAccessible: return compactAccessible
  case .regularAccessible: return regularAccessible
  case .compactOrAccessible: return compactOrAccessible
  }
}

As with all keyboard shortcuts it takes a few repetitions for me to learn it.

Select Next Occurrence (⌥⌘E)

A number of people let me know about another way to add multiple cursors using ⌥⌘E (in the Find menu as Select Next Occurrence). There’s also a Select Previous Occurrence (⌥⇧⌘E) but I doubt I’ll ever remember that.

Consider this example of two methods that check for compact size conditions. I want to change all four occurrences of compact to regular:

static private func compact(horizontalSizeClass: UserInterfaceSizeClass?,
  dynamicTypeSize: DynamicTypeSize) -> Bool {
  horizontalSizeClass == .compact
}

static private func compactAccessible(horizontalSizeClass: UserInterfaceSizeClass?,
  dynamicTypeSize: DynamicTypeSize) -> Bool {
  horizontalSizeClass == .compact &&
  dynamicTypeSize.isAccessibilitySize
}

Start by selecting the first compact, then use ⌥⌘E to select the next three occurrences:

Swift code with four instance of compact selected

Now type “regular” and all four occurrences are replaced and you’re left with four cursors in position if you need to make further changes:

Swift code with four instances of regular with trailing cursor.

Learn More

There’s a quick demo of multi-cursor editing in the WWDC 2018 State of the Union: