'Swift: How to check if a range is valid for a given string

I have written a swift function that takes a String and a Range as its parameters. How can I check that the range is valid for the string?

Edit: Nonsensical Example

func foo(text: String, range: Range<String.Index>) ->String? {
  // what can I do here to ensure valid range
  guard *is valid range for text* else {
    return nil
  }
  return text[range]
}

var str = "Hello, world"
let range = str.rangeOfString("world")
let str2 = "short"
let text = foo(str2, range: range!)


Solution 1:[1]

In Swift 3, this is easy: just get the string's character range and call contains to see if it contains your arbitrary range.

Edit: In Swift 4, a range no longer "contains" a range. A Swift 4.2 solution might look like this:

let string = // some string
let range = // some range of String.Index
let ok = range.clamped(to: string.startIndex..<string.endIndex) == range

If ok is true, it is safe to apply range to string.

Solution 2:[2]

Swift 5

extension String {
    func hasRange(_ range: NSRange) -> Bool {
        return Range(range, in: self) != nil
    }
}

Solution 3:[3]

Unfortunately, I was not able to test Matt's solution as I am using swift 2.2. However, using his idea I came up with ...

func foo(text: String, range: Range<String.Index>) -> String? {
  let r = text.startIndex..<text.endIndex
  if r.contains(range.startIndex) && r.contains(range.endIndex) {
    return text[range]
  } else {
    return nil
  }
}

If the start and end indices are ok then so must be the entire range.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Iulian Onofrei
Solution 2 Uladzimir
Solution 3 crackles