8

I'm not sure if it's a bug in XCode or I didn't understand ranges in Swift. Here is some code to show how range works:

let range = 0..<5
contains(range, 0) // true
contains(range, 5) // false
range.startIndex == 0 // true
range.endIndex == 5 // true

let str = "Hello, playground"
str.rangeOfString("Hello")! // 0..<5

Great! Now let's use it real code:

let str = "Hello, playground"
if let range = str.rangeOfString("Hello") {
    if range.startIndex == 0 {
        print("str starts with 'Hello'")
    }
}

I'm getting following error in line that reads if range.startIndex == 0 {

Cannot invoke '==' with an argument lis of type (String.index, IntegerLiteralConvertible)'

Mohsen
  • 64,437
  • 34
  • 159
  • 186

2 Answers2

14

The ~= operator in Swift

Sometimes, we have to check if a number is between a range, and as usual, we do something like :

Check if number is between 0 and 100 include

if number >=0 && number <= 100 {  
   // TODO:
}

It works, but we can do better and swiftier. The Swift Standard library have an ~= operator, so we can do instead :

if 0...100 ~= number {  
   // TODO:
 }
Premkumar
  • 231
  • 2
  • 7
9

rangeOfString actually returns a range of String.Indexs and not Ints; the two aren't comparable (even though the playground shows the range as 0..<5). You can read about the reasons for that in the answers to this question.

If you want your example to work then, instead of comparing range.startIndex with 0, you should compare it with str.startIndex:

let str = "Hello, playground"
if let range = str.rangeOfString("Hello") {
    if range.startIndex == str.startIndex {
        print("str starts with 'Hello'")
    }
}

If you need to compare to the range's startIndex with, say, the second character index in the string, then you can use the advance function to increment str.startIndex by 1 and compare range.startIndex to that:

let str = "Hello, playground"
if let range = str.rangeOfString("e") {
    if range.startIndex == advance(str.startIndex, 1) {
        print("str's 2nd character is 'e'")
    }
}

If you need to know the length of the range, then you can use the distance function:

let str = "Hello, playground"
if let range = str.rangeOfString("play") {
    let length = distance(range.startIndex, range.endIndex)
    print("found a range \(length) characters long")
}
Community
  • 1
  • 1
Mike S
  • 41,895
  • 11
  • 89
  • 84
  • Nice answer. I assume all this ceremony is for better Unicode support. For example it supports crazy characters like `"ﷺ"`. I just tried it – Mohsen Oct 29 '14 at 23:57
  • Exactly, it's like this for Unicode support. Basically it lets you jump around one character at a time, even if the characters are multi-byte. – Mike S Oct 30 '14 at 00:05
  • 3
    @Mohsen It's is not a crazy character but a sentence in arabic that says : « Peace upon him » (صلى الله عليه وآله وسلم) muslims use to praise the Prophet. As a convenience (as it is often used) this sentence exists as a one-packed ligature glyph (as many others). Hope it uncovers a mystery :-) – Stéphane de Luca Sep 09 '15 at 11:53