randombits
randombits

Reputation: 48450

Cannot increment beyond endIndex

I'm looking for the "Swift 3" way of handling an error where I try to increment the position of a string to an out of bounds index. I have an extension that looks like the following:

extension String {
  func substring(from: Int) -> String {
        let fromIndex = index(from: from)
        return substring(from: fromIndex)
  }
}

In implementation code, I have a loop which periodically takes chunks of a string and moves the index further in the string. My problem is I'm not sure what the Swift 3 way is of handling "End of String, do not proceed if we've reached the end"

Implementation code is something as trivial as this:

myStr = myStr.substring(from: pos + 1)

if pos + 1 is the end of the string, it shouldn't error out, but should instead just exit/return from my loop. What's the best way of doing that?

Upvotes: 1

Views: 3546

Answers (3)

Luca Angeletti
Luca Angeletti

Reputation: 59496

You can write something like this

extension String {
    func substring(from offset: Int) -> String {
        let fromIndex = index(self.startIndex, offsetBy: offset)
        return substring(from: fromIndex)
    }
}

Examples

"Hello world".substring(from: 0) // "Hello world"
"Hello world".substring(from: 1) // "ello world"
"Hello world".substring(from: 2) // "llo world"

What does happen if you pass the wrong param?

Something like this will generate a fatal error.

"Hello world".substring(from: 12)
fatal error: cannot increment beyond endIndex

You can make you code safer adding a guard statement like this

extension String {
    func substring(from: Int) -> String? {
        guard from < self.characters.count else { return nil }
        let fromIndex = index(self.startIndex, offsetBy: from)
        return substring(from: fromIndex)
    }
}

Upvotes: 4

Martin R
Martin R

Reputation: 539745

You can use the index(_, offsetBy:, limitedBy:) method to ensure that the index is not advanced beyond the end index:

extension String {
    func substring(from: Int) -> String? {
        guard let fromIndex = index(startIndex, offsetBy: from, limitedBy: endIndex) else {
            return nil
        }
        return substring(from: fromIndex)
    }
}

Upvotes: 3

Lars Blumberg
Lars Blumberg

Reputation: 21371

extension String {
    func substring(from index: Int) -> String {
        guard index < characters.count else { return "" }
        return substring(from: characters.index(startIndex, offsetBy: index))
    }
}

"12345".substring(from: 3) // "45"
"12345".substring(from: 9) // ""

Alternatively, you might want to return nil if index is out of bounds when you change the function's return type to String?

Upvotes: 1

Related Questions