Swift 2.0: NSRangeException, Range or index out of bounds

2.7k views Asked by At

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.

3

There are 3 answers

1
Ben On BEST ANSWER

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

0
Ryan Parman On

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)
0
F_Boris On

Maybe:

   Return regex.stringByReplacingMatchesInString{
        MainstringYouWantToReplaceSomethinIn,
        options: [.Anchored],
        range: NSMakeRange(0,self.MainstringYouWantToReplaceSomethinIn.count - 1),
        withTemplate: "xx"
    )
}
}