14

This is driving me nuts.

In Swift 2.2, it makes it impossible to subscript String with Int. For example:

let myString = "Test string"
let index = 0
let firstCharacter = myString[index]

This will result with a compile error, saying

'subscript' is unavailable: cannot subscript String with an Int, see the documentation comment for discussion

One workaround I see is to convert integer to the index type, but I can't figure out how..

ZGski
  • 2,398
  • 1
  • 21
  • 34
nekonari
  • 480
  • 1
  • 6
  • 13
  • 2
    Swift suddenly became really hard to use with 2.2... – nekonari May 18 '16 at 16:22
  • 2
    Possible duplicate of [Get nth character of a string in Swift programming language](http://stackoverflow.com/questions/24092884/get-nth-character-of-a-string-in-swift-programming-language) – Eric Aya May 18 '16 at 16:27
  • It was never possible to index a string with an `Int` in Swift. – Sulthan May 18 '16 at 19:51

5 Answers5

21

It annoyed the heck out of me too so I wrote an extension to deal with it:

extension String {
    subscript (index: Int) -> Character {
        let charIndex = self.startIndex.advancedBy(index)
        return self[charIndex]
    }

    subscript (range: Range<Int>) -> String {
        let startIndex = self.startIndex.advancedBy(range.startIndex)
        let endIndex = startIndex.advancedBy(range.count)

        return self[startIndex..<endIndex]
    }
}

// Usage
let str = "Hello world"

print(str[0])       // H
print(str[0..<5])   // Hello

Updated for Swift 4.x:

extension String {
    subscript (index: Int) -> Character {
        let charIndex = self.index(self.startIndex, offsetBy: index)
        return self[charIndex]
    }

    subscript (range: Range<Int>) -> Substring {
        let startIndex = self.index(self.startIndex, offsetBy: range.startIndex)
        let stopIndex = self.index(self.startIndex, offsetBy: range.startIndex + range.count)
        return self[startIndex..<stopIndex]
    }

}

let s = "‍‍‍ family"

print(s[0])      // ‍‍‍
print(s[2..<8])  // family
Jaymon
  • 5,363
  • 3
  • 34
  • 34
Code Different
  • 90,614
  • 16
  • 144
  • 163
18

It's not that subscripting is impossible necessarily, it just takes one extra step to get the same results as before. Below, I've done the same thing as you, but in Swift 2.2

let myString = "Test string"
let intForIndex = 0
let index = myString.startIndex.advancedBy(intForIndex)
let firstCharacter = myString[index]

Swift 3.x + 4.x

let myString = "Test string"
let intForIndex = 0
let index = myString.index(myString.startIndex, offsetBy: intForIndex)
let firstCharacter = myString[index]

EDIT 1:

Updated code so you can use the Int that was passed into the "index" value elsewhere.


Syntax Edits:

I'll consistently update this answer to support the newest version of Swift.

ZGski
  • 2,398
  • 1
  • 21
  • 34
  • This does the trick, but what about converting the other way? – nekonari May 18 '16 at 17:20
  • Taking an .Index type and turn it into Int. – nekonari May 18 '16 at 17:21
  • Are you looking to directly convert `Index` to `Int`, or are your looking to use the `Int` to find a character in a `String`? – ZGski May 18 '16 at 18:39
  • No for other use. I needed an int so I can manipulate another array at the corresponding index according to the Character. I ended mapping the CharacterView into array of Characters then work with it. Still not ideal since it wastes time on conversion :( – nekonari May 18 '16 at 20:05
  • I've updated my answer so you can re-use the `Int` passed into "index". – ZGski May 18 '16 at 20:18
  • @ZGski when I tried to insert "\n" at the middle it removed half of the string. But it works well when I use normal characters. Do you know how to solve it? – JkAlombro Jul 24 '18 at 01:33
  • @JkAlombro What does your `String` look like exactly? – ZGski Jul 25 '18 at 15:36
  • @ZGski The string looks like this `5B495473-ED0A-4516-ACBC-C2F36B59EED5`. I want to insert "\n" in the middle so that the other half goes to next line but it removes the half of the string instead – JkAlombro Jul 26 '18 at 05:29
  • @JkAlombro This sounds like an issue related to the way your `UILabel` is set up... See **[this post](https://stackoverflow.com/questions/24134905/how-do-i-set-adaptive-multiline-uilabel-text)**. – ZGski Jul 29 '18 at 02:19
  • @ZGski yeah, seems like I didn't need to insert newline after all. All I had to do is set the number of lines allowed for my UILabel to 2. Thanks sir. – JkAlombro Jul 30 '18 at 03:04
4

An example for swift 4:

let myString = "Test string"
let index = 0
let firstCharacter = myString[String.Index(encodedOffset: index)]
Linh Dao
  • 1,305
  • 1
  • 19
  • 31
0

An easy cheat is to convert the string to an array of characters, which you can index with an Int:

let a = Array("hello")
for i in a.indices {
   print(a[i])
}
Jim Haungs
  • 184
  • 10
-1

ZGski answer updated to Swift 3

let testText = "Test text 123"  
let position = 11  
let index = testText.characters.index(testText.startIndex, offsetBy: position)  
let character = testText[index] // "2"
AT82
  • 71,416
  • 24
  • 140
  • 167
Randalg
  • 1
  • 2