0

What is the best way to replace:

.doOnComplete {
    // Implementation
}

with

.do(
    onComplete: {
        // Implementation
    }
)

throughout a large Swift codebase? Given that there are a large number of these manually replacing is not an option.

wp78de
  • 18,207
  • 7
  • 43
  • 71
  • refactoring should work – GIJOW May 09 '18 at 21:05
  • @GIJOW are you referring to the refactoring function in XCode? if we would like to just change the method name to `doOnComplete1` that would work. Not sure if it would work if we would like to roll existing impl into an argument. – user5661669 May 09 '18 at 21:07
  • Couldn't you use the finder and set it to replace one with the other? – D. Greg May 09 '18 at 21:17
  • 1
    @D.Greg You can replace `.doOnComplete {` with `.do(onComplete: {` but what about the trailing `})` ? What if there are nested implementation inside? Given that we do not want to fix a few hundreds of these manually. – user5661669 May 09 '18 at 21:20
  • @user5661669 Who would? lol. If the auto-refactoring doesn't work, there's not much else you can do. I had a project last year and ended up doing it that way. Once you change the first half errors are thrown. So just find `})` and fix the ones that are throwing errors (be sure it's the first one throwing an error in each file). It's a slow process, but it works. – D. Greg May 09 '18 at 21:25
  • Couldn't you just replace `.doOnComplete` with `.do` since the `onComplete` part can be treated as a trailing closure? – vacawama May 09 '18 at 21:57
  • @vacawama unfortunately no. There are other parameters with default values, we have to specifically call out `onComplete`. – user5661669 May 09 '18 at 22:37

3 Answers3

1

Depending on the complexity of your code, this could be very hard to achieve.

It the correct approach is indeed to try to capture the implementation block. However, it is important to look out for balanced curly braces, e.g. like this:

\.doOnComplete\s*(\{(?>[^{}]+|(?1))*\})

and then replace with

.do(\n\tonComplete: $1\t\n)

Demo

PS: I tried to pretty print the code but you will have to reformat the code anyways.

wp78de
  • 18,207
  • 7
  • 43
  • 71
0

The find and replace feature in Xcode has a regular expression option. You should be able to craft a regular expression to do this.

Duncan C
  • 128,072
  • 22
  • 173
  • 272
0

In the Xcode-Menu Find>Find and Replace in Project...(or alternatively ⌥⇧⌘F). You get at the place, where you normally find the Project Navigator, now the Find Navigator. At the very top select instead of 'Text' 'Regular Expression':

Xcode Find Navigator

Then type in the first Text Field (notice: my method doesn't work, if your blocks contain inside the curly braces some more curly braces)

( *)\.doOnComplete \{([^\}]*)\}

Press enter after it. Below the second text field, there should show all occurrences of the .doOnComplete Block.

Now you can type (every '[enter]' means control+q followed by enter)

$1.do([enter]$1onComplete: {$2}[enter]$1)

in the second text field. After that, you should select one of the found occurrences below the second text field and press the 'Replace' Button. If the replacing is ok and everything in the block is still there, you can press the 'Replace All' Button, and everything in the whole project should be replaced.

Josef Zoller
  • 921
  • 2
  • 8
  • 24