1

I don't understand what to do with the issue reported by the compiler. I tried to create a Range, but it says Index is not known:

           //let range = matches.first!.range.location
            let range = Range(
                start:matches.first!.range.location,
                end: matches.first!.range.location+matches.first!.range.length
            )
            id = text[range]
            var t = text
            t.removeRange(range)
            return t

Compiler says: Cannot invoke 'removeRange' with an argument list of type '(Range)' on t.removeRange(range). I'm pretty sure it's evident, but I lost a great deal of time on such a small issue… any help highly appreciated!

Stéphane de Luca
  • 12,745
  • 9
  • 57
  • 95
  • 1
    Most probably the "incompatibility" between NSRange (used for NSString) and Swift Range (used for Swift String), as in http://stackoverflow.com/questions/27880650/swift-extract-regex-matches or http://stackoverflow.com/questions/25138339/nsrange-to-rangestring-index. – Martin R Jul 31 '15 at 19:09

3 Answers3

2

As your error says that:

Cannot invoke 'removeRange' with an argument list of type '(Range)'

Means there is a problem with your range instance type and removeRange function will only accept an argument with type Range<String.Index> and its syntax is :

/// Remove the indicated `subRange` of characters
///
/// Invalidates all indices with respect to `self`.
///
/// Complexity: O(\ `count(self)`\ ).
mutating func removeRange(subRange: Range<String.Index>)

And here is working example with removeRange:

var welcome = "hello there"
let range = advance(welcome.endIndex, -6)..<welcome.endIndex
welcome.removeRange(range)
println(welcome)  //hello

Hope this will help.

Dharmesh Kheni
  • 71,228
  • 33
  • 160
  • 165
1

Swift 2.2 example of removing first 4 characters:

let range = text.startIndex..<text.startIndex.advancedBy(4)
text.removeRange(range)

That first line feels verbose. I hope newer Swift versions improve upon it.

Graham Perks
  • 23,007
  • 8
  • 61
  • 83
0

Here is the working equivalent snippet:

static func unitTest() {
    let text = "abbbbbc"
    let tag = Tag(id: "")
    tag.regex = "b+"
    print ("Unit test tag.foundIn(\(text)) ? = \(tag.foundIn(text))")
}

func foundIn(text: String) -> (id:String, remainingText:String)? {

    // if a regex is provided, use it to capture, and keep the capture as a tag ID
    if let regex = regex {
        let r = Regex(regex)                        // text =~ regex
        let matches = r.matches(text)

        if matches.count >= 1 {
            let first   = matches.first!.range
            let start   = advance(text.startIndex,  first.location)
            let end     = advance(start,            first.length-1)

            let range = Range(start: start, end: end)
            id = text[range]
            var t = text
            t.removeRange(range)
            return (id, t)
        }

        return nil
    }
    else if let range = text.rangeOfString(id) {
        var t = text
        t.removeRange(range)
        return (id, t)
    }
    else {
        return nil
    }
}

The unit test returns :

Unit test tag.foundIn(abbbbbc) ? = Optional(("bbbbb", "ac"))
Stéphane de Luca
  • 12,745
  • 9
  • 57
  • 95
  • This *compiles*, but I suggests that you have a look at the threads that I linked to above and the various comments. Your method of creating a Swift range from NSRange can produce wrong results for "special characters" such as Emojis or "flags". – Martin R Jul 31 '15 at 19:30
  • Not sure understand your remark as I use advance() functions which nicely handle unicode. I have augmented my answer ti include unitTest and the result. – Stéphane de Luca Aug 01 '15 at 10:43
  • It may be that I mixed things up (and I apologize in that case). But I cannot check your code because it is not self-contained (Tag, Regex undefined). – Martin R Aug 01 '15 at 10:51