2

Context: I come from 15-20 years of JavaScript, Ruby and (modern) PHP. I've been poking at Swift over the last year, and I'm brand-new to Cocoa.

Here's a simplified test case that I'm running in Xcode 7.0 β2:

#! /usr/bin/env swift

import Foundation

// Extend the String object with helpers
extension String {

    // String.replace(); similar to JavaScript's String.replace() and Ruby's String.gsub()
    func replace(pattern: String, replacement: String) -> String {

        // Debugging
        print(self.characters.count)
        print(NSMakeRange(0, self.characters.count - 1))

        let regex = try! NSRegularExpression(
            pattern: pattern,
            options: [.CaseInsensitive]
        )

        return regex.stringByReplacingMatchesInString(
            replacement,
            options: [.Anchored],
            range: NSMakeRange(0, self.characters.count - 1),
            withTemplate: "xx"
        )
    }
}

let prefix = "abc     123".replace("\\s+", replacement: " ")

print(prefix)

The two debugging lines display:

11
(0,10)

After that, the app crashes with the following message:

2015-06-24 23:18:45.027 swift[42912:648900] *** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[NSRegularExpression enumerateMatchesInString:options:range:usingBlock:]: Range or index out of bounds'

I've looked over the following documentation, but nothing is jumping out to me:

I can only think that the issue has something to do with passing an NSRange instance as a parameter to the stringByReplacingMatchesInString() method, but I've tried adjusting the value to NSRange(0,1) and NSRange(1,2) expecting to see something that would help, but it's still throwing the exception.

As I wrote in the title, I'm working in Swift 2.0.

Mayank Jain
  • 5,663
  • 7
  • 32
  • 65
Ryan Parman
  • 6,855
  • 1
  • 29
  • 43
  • I dont' know if it is the cause of your issue, but take a look here about using NSRage http://nshipster.com/nsrange/ – Andrea Jun 25 '15 at 07:00

3 Answers3

2

I see that the first argument to stringByReplacingMatchesInString is 'replacement'. Should this be 'self'?

Ben
  • 46
  • 4
  • *facepalm*. Yes, you're right. But then — where does the _replacement_ value go? I have my compiled regex, and I'm calling `stringByReplacingMatchesInString()` on it, passing `self`. – Ryan Parman Jun 25 '15 at 07:05
1

After @Ben’s answer, I feel stupid. That kicked-off a little more poking around, and I figured it out. Here's the code.

#! /usr/bin/env swift

import Foundation

// Extend the String object with helpers
extension String {

    // String.replace(); similar to JavaScript's String.replace() and Ruby's String.gsub()
    func replace(pattern: String, replacement: String) -> String {

        let regex = try! NSRegularExpression(
            pattern: pattern,
            options: [.CaseInsensitive]
        )

        return regex.stringByReplacingMatchesInString(
            self,
            options: [.WithTransparentBounds],
            range: NSMakeRange(0, self.characters.count),
            withTemplate: replacement
        )
    }
}

let prefix = "abc     123".replace("(\\s+)", replacement: " ")

print(prefix)
Ryan Parman
  • 6,855
  • 1
  • 29
  • 43
0

Maybe:

   Return regex.stringByReplacingMatchesInString{
        MainstringYouWantToReplaceSomethinIn,
        options: [.Anchored],
        range: NSMakeRange(0,self.MainstringYouWantToReplaceSomethinIn.count - 1),
        withTemplate: "xx"
    )
}
}
Nikolay Kostov
  • 16,433
  • 23
  • 85
  • 123
F_Boris
  • 170
  • 9