222

It's time to admit defeat...

In Objective-C, I could use something like:

NSString* str = @"abcdefghi";
[str rangeOfString:@"c"].location; // 2

In Swift, I see something similar:

var str = "abcdefghi"
str.rangeOfString("c").startIndex

...but that just gives me a String.Index, which I can use to subscript back into the original string, but not extract a location from.

FWIW, that String.Index has a private ivar called _position that has the correct value in it. I just don't see how it's exposed.

I know I could easily add this to String myself. I'm more curious about what I'm missing in this new API.

Matt Wilding
  • 20,115
  • 3
  • 67
  • 95

33 Answers33

259

You are not the only one who couldn't find the solution.

String doesn't implement RandomAccessIndexType. Probably because they enable characters with different byte lengths. That's why we have to use string.characters.count (count or countElements in Swift 1.x) to get the number of characters. That also applies to positions. The _position is probably an index into the raw array of bytes and they don't want to expose that. The String.Index is meant to protect us from accessing bytes in the middle of characters.

That means that any index you get must be created from String.startIndex or String.endIndex (String.Index implements BidirectionalIndexType). Any other indices can be created using successor or predecessor methods.

Now to help us with indices, there is a set of methods (functions in Swift 1.x):

Swift 4.x

let text = "abc"
let index2 = text.index(text.startIndex, offsetBy: 2) //will call succ 2 times
let lastChar: Character = text[index2] //now we can index!

let characterIndex2 = text.index(text.startIndex, offsetBy: 2)
let lastChar2 = text[characterIndex2] //will do the same as above

let range: Range<String.Index> = text.range(of: "b")!
let index: Int = text.distance(from: text.startIndex, to: range.lowerBound)

Swift 3.0

let text = "abc"
let index2 = text.index(text.startIndex, offsetBy: 2) //will call succ 2 times
let lastChar: Character = text[index2] //now we can index!

let characterIndex2 = text.characters.index(text.characters.startIndex, offsetBy: 2)
let lastChar2 = text.characters[characterIndex2] //will do the same as above

let range: Range<String.Index> = text.range(of: "b")!
let index: Int = text.distance(from: text.startIndex, to: range.lowerBound)

Swift 2.x

let text = "abc"
let index2 = text.startIndex.advancedBy(2) //will call succ 2 times
let lastChar: Character = text[index2] //now we can index!
let lastChar2 = text.characters[index2] //will do the same as above

let range: Range<String.Index> = text.rangeOfString("b")!
let index: Int = text.startIndex.distanceTo(range.startIndex) //will call successor/predecessor several times until the indices match

Swift 1.x

let text = "abc"
let index2 = advance(text.startIndex, 2) //will call succ 2 times
let lastChar: Character = text[index2] //now we can index!

let range = text.rangeOfString("b")
let index: Int = distance(text.startIndex, range.startIndex) //will call succ/pred several times

Working with String.Index is cumbersome but using a wrapper to index by integers (see https://stackoverflow.com/a/25152652/669586) is dangerous because it hides the inefficiency of real indexing.

Note that Swift indexing implementation has the problem that indices/ranges created for one string cannot be reliably used for a different string, for example:

Swift 2.x

let text: String = "abc"
let text2: String = ""

let range = text.rangeOfString("b")!

//can randomly return a bad substring or throw an exception
let substring: String = text2[range]

//the correct solution
let intIndex: Int = text.startIndex.distanceTo(range.startIndex)
let startIndex2 = text2.startIndex.advancedBy(intIndex)
let range2 = startIndex2...startIndex2

let substring: String = text2[range2]

Swift 1.x

let text: String = "abc"
let text2: String = ""

let range = text.rangeOfString("b")

//can randomly return nil or a bad substring 
let substring: String = text2[range] 

//the correct solution
let intIndex: Int = distance(text.startIndex, range.startIndex)    
let startIndex2 = advance(text2.startIndex, intIndex)
let range2 = startIndex2...startIndex2

let substring: String = text2[range2]  
Yevhen
  • 1,048
  • 1
  • 14
  • 24
Sulthan
  • 128,090
  • 22
  • 218
  • 270
  • 1
    Awkward thought it may be, this seems to be the answer. Hopefully those two range functions will make it into the documentation sometime before the final release. – Matt Wilding Jun 05 '14 at 16:52
  • What type is `range` in `var range = text.rangeOfString("b")` – zaph Jun 14 '14 at 19:19
  • `String.Index` is a type? It seems that range should be, well, a range: a starting index and an length else call it index. So I take it that the Swift team is playing fast and loose with the English language, calling an index a range? (I am ignoring Plane 1 unicode, that is an existing problem that was not fixed.) – zaph Jun 14 '14 at 19:36
  • 5
    @Zaph Every `Collection` has a `typealias IndexType`. For arrays, it is defined as `Int`, for `String` it is defined as `String.Index`. Both arrays and strings can also use ranges (to create subarrays and substrings). The range is a special type `Range`. For strings, it's `Range`, for arrays `Range`. – Sulthan Jun 15 '14 at 11:03
  • How about for more than just 1 character? – User Sep 26 '14 at 21:36
  • @macdonjo You work with ranges (or whatever they call it now) of indices instead of one index. The same as with arrays. – Sulthan Sep 27 '14 at 10:11
  • I got an error compiling this code: `'Range?' does not have a member named 'startIndex'`. I had to change `range.startIndex` to `range!.startIndex`. – Liron Yahdav Jan 05 '15 at 06:46
  • 1
    In `Swift 2.0`, `distance(text.startIndex, range.startIndex)` becomes `text.startIndex.distanceTo(range.startIndex)` – superarts.org Oct 10 '15 at 09:15
  • Swift has a bad habit of making simple concepts incredibly complicated. – devios1 Mar 09 '16 at 21:52
  • `str.startsWith(search)` becomes `str.rangeOfString(search) != nil && (str.startIndex.distanceTo(str.rangeOfString(search)!.startIndex) == 0)`. Unreal. – devios1 Mar 09 '16 at 21:59
  • 1
    @devios `String`, exactly like `NSString` in Foundation has a method called `hasPrefix(_:)`. – Sulthan Mar 09 '16 at 22:03
90

Swift 3.0 makes this a bit more verbose:

let string = "Hello.World"
let needle: Character = "."
if let idx = string.characters.index(of: needle) {
    let pos = string.characters.distance(from: string.startIndex, to: idx)
    print("Found \(needle) at position \(pos)")
}
else {
    print("Not found")
}

Extension:

extension String {
    public func index(of char: Character) -> Int? {
        if let idx = characters.index(of: char) {
            return characters.distance(from: startIndex, to: idx)
        }
        return nil
    }
}

In Swift 2.0 this has become easier:

let string = "Hello.World"
let needle: Character = "."
if let idx = string.characters.indexOf(needle) {
    let pos = string.startIndex.distanceTo(idx)
    print("Found \(needle) at position \(pos)")
}
else {
    print("Not found")
}

Extension:

extension String {
    public func indexOfCharacter(char: Character) -> Int? {
        if let idx = self.characters.indexOf(char) {
            return self.startIndex.distanceTo(idx)
        }
        return nil
    }
}

Swift 1.x implementation:

For a pure Swift solution one can use:

let string = "Hello.World"
let needle: Character = "."
if let idx = find(string, needle) {
    let pos = distance(string.startIndex, idx)
    println("Found \(needle) at position \(pos)")
}
else {
    println("Not found")
}

As an extension to String:

extension String {
    public func indexOfCharacter(char: Character) -> Int? {
        if let idx = find(self, char) {
            return distance(self.startIndex, idx)
        }
        return nil
    }
}
Pascal
  • 16,846
  • 4
  • 60
  • 69
27

Swift 5.0

public extension String {  
  func indexInt(of char: Character) -> Int? {
    return firstIndex(of: char)?.utf16Offset(in: self)
  }
}

Swift 4.0

public extension String {  
  func indexInt(of char: Character) -> Int? {
    return index(of: char)?.encodedOffset        
  }
}
Vincenso
  • 516
  • 4
  • 8
23
extension String {

    // MARK: - sub String
    func substringToIndex(index:Int) -> String {
        return self.substringToIndex(advance(self.startIndex, index))
    }
    func substringFromIndex(index:Int) -> String {
        return self.substringFromIndex(advance(self.startIndex, index))
    }
    func substringWithRange(range:Range<Int>) -> String {
        let start = advance(self.startIndex, range.startIndex)
        let end = advance(self.startIndex, range.endIndex)
        return self.substringWithRange(start..<end)
    }

    subscript(index:Int) -> Character{
        return self[advance(self.startIndex, index)]
    }
    subscript(range:Range<Int>) -> String {
        let start = advance(self.startIndex, range.startIndex)
            let end = advance(self.startIndex, range.endIndex)
            return self[start..<end]
    }


    // MARK: - replace
    func replaceCharactersInRange(range:Range<Int>, withString: String!) -> String {
        var result:NSMutableString = NSMutableString(string: self)
        result.replaceCharactersInRange(NSRange(range), withString: withString)
        return result
    }
}
Pang
  • 9,564
  • 146
  • 81
  • 122
huiquhome
  • 247
  • 2
  • 2
  • 7
    Thought about doing this, but I think it is a problem that it hides the semantics of string access. Imagine creating an API for accessing linked lists that looks just like the API for an array. People would like write horribly inefficient code. – Erik Engheim Nov 21 '14 at 12:48
  • In many cases, there are still packets of characters that are only utf8. It's just nuts to not have simple functions like indexOf(), substr(), and other functions similar to the c library functions. Trying to make everything deal with NLS when it's not present represents the weakness of the current String design. there is literally no reason why String can not be an array of Character and Character can document the number of 'bytes' and contain those bytes. A Character can be a struct or object that works effectively to contain all the details of the Character. – Grwww Jun 30 '23 at 03:30
16

I have found this solution for swift2:

var str = "abcdefghi"
let indexForCharacterInString = str.characters.indexOf("c") //returns 2
VYT
  • 1,071
  • 19
  • 35
8

I'm not sure how to extract the position from String.Index, but if you're willing to fall back on some Objective-C frameworks, you can bridge to objective-c and do it the same way you used to.

"abcdefghi".bridgeToObjectiveC().rangeOfString("c").location

It seems like some NSString methods haven't yet been (or maybe won't be) ported to String. Contains also comes to mind.

Connor Pearson
  • 63,902
  • 28
  • 145
  • 142
  • It actually appears that accessing the location property of the return value is enough for the compiler to infer an NSString type, so the `bridgeToObjectiveC()` call isn't needed. My problem seems to manifest only when calling `rangeOfString` on previously existing Swift String. Seems like an API issue... – Matt Wilding Jun 04 '14 at 05:29
  • that's interesting. I didn't know it inferred in those cases. Well when it's already a String you can always use the bridge. – Connor Pearson Jun 04 '14 at 05:35
8

Here is a clean String extention that answers the question:

Swift 3:

extension String {
    var length:Int {
        return self.characters.count
    }

    func indexOf(target: String) -> Int? {

        let range = (self as NSString).range(of: target)

        guard range.toRange() != nil else {
            return nil
        }

        return range.location

    }
    func lastIndexOf(target: String) -> Int? {



        let range = (self as NSString).range(of: target, options: NSString.CompareOptions.backwards)

        guard range.toRange() != nil else {
            return nil
        }

        return self.length - range.location - 1

    }
    func contains(s: String) -> Bool {
        return (self.range(of: s) != nil) ? true : false
    }
}

Swift 2.2:

extension String {    
    var length:Int {
        return self.characters.count
    }

    func indexOf(target: String) -> Int? {

        let range = (self as NSString).rangeOfString(target)

        guard range.toRange() != nil else {
            return nil
        }

        return range.location

    }
    func lastIndexOf(target: String) -> Int? {



        let range = (self as NSString).rangeOfString(target, options: NSStringCompareOptions.BackwardsSearch)

        guard range.toRange() != nil else {
            return nil
        }

        return self.length - range.location - 1

    }
    func contains(s: String) -> Bool {
        return (self.rangeOfString(s) != nil) ? true : false
    }
}
Ryan Cocuzzo
  • 3,109
  • 7
  • 35
  • 64
YanSte
  • 10,661
  • 3
  • 57
  • 53
7

You can also find indexes of a character in a single string like this,

extension String {

  func indexes(of character: String) -> [Int] {

    precondition(character.count == 1, "Must be single character")

    return self.enumerated().reduce([]) { partial, element  in
      if String(element.element) == character {
        return partial + [element.offset]
      }
      return partial
    }
  }

}

Which gives the result in [String.Distance] ie. [Int], like

"apple".indexes(of: "p") // [1, 2]
"element".indexes(of: "e") // [0, 2, 4]
"swift".indexes(of: "j") // []
Sandeep
  • 20,908
  • 7
  • 66
  • 106
6

Swift 5

Find index of substring

let str = "abcdecd"
if let range: Range<String.Index> = str.range(of: "cd") {
    let index: Int = str.distance(from: str.startIndex, to: range.lowerBound)
    print("index: ", index) //index: 2
}
else {
    print("substring not found")
}

Find index of Character

let str = "abcdecd"
if let firstIndex = str.firstIndex(of: "c") {
    let index: Int = str.distance(from: str.startIndex, to: firstIndex)
    print("index: ", index)   //index: 2
}
else {
    print("symbol not found")
}
Viktor
  • 1,155
  • 14
  • 23
5

If you want to use familiar NSString, you can declare it explicitly:

var someString: NSString = "abcdefghi"

var someRange: NSRange = someString.rangeOfString("c")

I'm not sure yet how to do this in Swift.

Logan
  • 52,262
  • 20
  • 99
  • 128
  • 1
    This certainly works, and it seems the compiler is pretty aggressive in inferring NSString types for you. I was really hoping for a pure Swift way of doing this, since it seems like a common enough use case. – Matt Wilding Jun 04 '14 at 05:31
  • Yea, I'm looking around, but I don't see it. It's possible they focused on areas not supported by ObjC because they can fill in these gaps w/o too many capabilities lost. Just thinking out loud :) – Logan Jun 04 '14 at 05:32
4

If you want to know the position of a character in a string as an int value use this:

let loc = newString.range(of: ".").location
3

This worked for me,

var loc = "abcdefghi".rangeOfString("c").location
NSLog("%d", loc);

this worked too,

var myRange: NSRange = "abcdefghi".rangeOfString("c")
var loc = myRange.location
NSLog("%d", loc);
rdelmar
  • 103,982
  • 12
  • 207
  • 218
  • Both of these seem to fallback on NSString's behavior somehow. In my playground, I was using an intermediate variable for the string. `var str = "abcdef"; str.rangeOfString("c").location` raises an error about String.Index not having a member named location... – Matt Wilding Jun 04 '14 at 05:21
  • 1
    It works just because "string" is NSString and not Swift's String – gderaco Aug 02 '14 at 19:10
3

I know this is old and an answer has been accepted, but you can find the index of the string in a couple lines of code using:

var str : String = "abcdefghi"
let characterToFind: Character = "c"
let characterIndex = find(str, characterToFind)  //returns 2

Some other great information about Swift strings here Strings in Swift

Jack
  • 985
  • 7
  • 11
2

Variable type String in Swift contains different functions compared to NSString in Objective-C . And as Sulthan mentioned,

Swift String doesn't implement RandomAccessIndex

What you can do is downcast your variable of type String to NSString (this is valid in Swift). This will give you access to the functions in NSString.

var str = "abcdefghi" as NSString
str.rangeOfString("c").locationx   // returns 2
Alexander G
  • 256
  • 2
  • 7
2

If you think about it, you actually don't really need the exact Int version of the location. The Range or even the String.Index is enough to get the substring out again if needed:

let myString = "hello"

let rangeOfE = myString.rangeOfString("e")

if let rangeOfE = rangeOfE {
    myString.substringWithRange(rangeOfE) // e
    myString[rangeOfE] // e

    // if you do want to create your own range
    // you can keep the index as a String.Index type
    let index = rangeOfE.startIndex
    myString.substringWithRange(Range<String.Index>(start: index, end: advance(index, 1))) // e

    // if you really really need the 
    // Int version of the index:
    let numericIndex = distance(index, advance(index, 1)) // 1 (type Int)
}
NatashaTheRobot
  • 6,879
  • 4
  • 32
  • 27
  • The best answer for me is that func indexOf(target: String) -> Int { return (self as NSString).rangeOfString(target).location } – YanSte Sep 14 '15 at 11:30
2

The Simplest Way is:

In Swift 3:

 var textViewString:String = "HelloWorld2016"
    guard let index = textViewString.characters.index(of: "W") else { return }
    let mentionPosition = textViewString.distance(from: index, to: textViewString.endIndex)
    print(mentionPosition)
Pragnesh Vitthani
  • 2,532
  • 20
  • 28
1

String is a bridge type for NSString, so add

import Cocoa

to your swift file and use all the "old" methods.

IgnazioC
  • 4,554
  • 4
  • 33
  • 46
1

In terms of thinking this might be called an INVERSION. You discover the world is round instead of flat. "You don't really need to know the INDEX of the character to do things with it." And as a C programmer I found that hard to take too! Your line "let index = letters.characters.indexOf("c")!" is enough by itself. For example to remove the c you could use...(playground paste in)

    var letters = "abcdefg"
  //let index = letters.rangeOfString("c")!.startIndex //is the same as
    let index = letters.characters.indexOf("c")!
    range = letters.characters.indexOf("c")!...letters.characters.indexOf("c")!
    letters.removeRange(range)
    letters

However, if you want an index you need to return an actual INDEX not an Int as an Int value would require additional steps for any practical use. These extensions return an index, a count of a specific character, and a range which this playground plug-in-able code will demonstrate.

extension String
{
    public func firstIndexOfCharacter(aCharacter: Character) -> String.CharacterView.Index? {

        for index in self.characters.indices {
            if self[index] == aCharacter {
                return index
            }

        }
        return nil
    }

    public func returnCountOfThisCharacterInString(aCharacter: Character) -> Int? {

        var count = 0
        for letters in self.characters{

            if aCharacter == letters{

                count++
            }
        }
        return count
    }


    public func rangeToCharacterFromStart(aCharacter: Character) -> Range<Index>? {

        for index in self.characters.indices {
            if self[index] == aCharacter {
                let range = self.startIndex...index
                return range
            }

        }
        return nil
    }

}



var MyLittleString = "MyVery:important String"

var theIndex = MyLittleString.firstIndexOfCharacter(":")

var countOfColons = MyLittleString.returnCountOfThisCharacterInString(":")

var theCharacterAtIndex:Character = MyLittleString[theIndex!]

var theRange = MyLittleString.rangeToCharacterFromStart(":")
MyLittleString.removeRange(theRange!)
Mountain Man
  • 252
  • 2
  • 10
1

Swift 4 Complete Solution:

OffsetIndexableCollection (String using Int Index)

https://github.com/frogcjn/OffsetIndexableCollection-String-Int-Indexable-

let a = "01234"

print(a[0]) // 0
print(a[0...4]) // 01234
print(a[...]) // 01234

print(a[..<2]) // 01
print(a[...2]) // 012
print(a[2...]) // 234
print(a[2...3]) // 23
print(a[2...2]) // 2

if let number = a.index(of: "1") {
    print(number) // 1
    print(a[number...]) // 1234
}

if let number = a.index(where: { $0 > "1" }) {
    print(number) // 2
}
frogcjn
  • 819
  • 5
  • 21
1

extension String {

//Fucntion to get the index of a particular string
func index(of target: String) -> Int? {
    if let range = self.range(of: target) {
        return characters.distance(from: startIndex, to: range.lowerBound)
    } else {
        return nil
    }
}
//Fucntion to get the last index of occurence of a given string
func lastIndex(of target: String) -> Int? {
    if let range = self.range(of: target, options: .backwards) {
        return characters.distance(from: startIndex, to: range.lowerBound)
    } else {
        return nil
    }
}

}

1

You can find the index number of a character in a string with this:

var str = "abcdefghi"
if let index = str.firstIndex(of: "c") {
    let distance = str.distance(from: str.startIndex, to: index)
    // distance is 2
}
Ale Mohamad
  • 372
  • 4
  • 7
0

If you are looking for easy way to get index of Character or String checkout this library http://www.dollarswift.org/#indexof-char-character-int

You can get the indexOf from a string using another string as well or regex pattern

Encore PTL
  • 8,084
  • 10
  • 43
  • 78
0

To get index of a substring in a string with Swift 2:

let text = "abc"
if let range = text.rangeOfString("b") {
   var index: Int = text.startIndex.distanceTo(range.startIndex) 
   ...
}
Tony
  • 1,551
  • 20
  • 21
0

In swift 2.0

var stringMe="Something In this.World"
var needle="."
if let idx = stringMe.characters.indexOf(needle) {
    let pos=stringMe.substringFromIndex(idx)
    print("Found \(needle) at position \(pos)")
}
else {
    print("Not found")
}
Yoosaf Abdulla
  • 3,722
  • 4
  • 31
  • 34
0

In Swift 2.0, the following function returns a substring before a given character.

func substring(before sub: String) -> String {
    if let range = self.rangeOfString(sub),
        let index: Int = self.startIndex.distanceTo(range.startIndex) {
        return sub_range(0, index)
    }
    return ""
}
Ky -
  • 30,724
  • 51
  • 192
  • 308
superarts.org
  • 7,009
  • 1
  • 58
  • 44
0
let mystring:String = "indeep";
let findCharacter:Character = "d";

if (mystring.characters.contains(findCharacter))
{
    let position = mystring.characters.indexOf(findCharacter);
    NSLog("Position of c is \(mystring.startIndex.distanceTo(position!))")

}
else
{
    NSLog("Position of c is not found");
}
Jón Trausti Arason
  • 4,548
  • 1
  • 39
  • 46
Indeep
  • 11
0

I play with following

extension String {
    func allCharactes() -> [Character] {
         var result: [Character] = []
         for c in self.characters {
             result.append(c)
         }
         return 
    }
}

until I understand the provided one's now it's just Character array

and with

let c = Array(str.characters)
Peter Ahlberg
  • 1,359
  • 2
  • 24
  • 26
0

If you only need the index of a character the most simple, quick solution (as already pointed out by Pascal) is:

let index = string.characters.index(of: ".")
let intIndex = string.distance(from: string.startIndex, to: index)
Markymark
  • 2,804
  • 1
  • 32
  • 37
0

On the subject of turning a String.Index into an Int, this extension works for me:

public extension Int {
    /// Creates an `Int` from a given index in a given string
    ///
    /// - Parameters:
    ///    - index:  The index to convert to an `Int`
    ///    - string: The string from which `index` came
    init(_ index: String.Index, in string: String) {
        self.init(string.distance(from: string.startIndex, to: index))
    }
}

Example usage relevant to this question:

var testString = "abcdefg"

Int(testString.range(of: "c")!.lowerBound, in: testString)     // 2

testString = "‍‍‍\u{1112}\u{1161}\u{11AB}"

Int(testString.range(of: "")!.lowerBound, in: testString) // 0
Int(testString.range(of: "‍‍‍")!.lowerBound, in: testString)    // 1
Int(testString.range(of: "한")!.lowerBound, in: testString)    // 5

Important:

As you can tell, it groups extended grapheme clusters and joined characters differently than String.Index. Of course, this is why we have String.Index. You should keep in mind that this method considers clusters to be singular characters, which is closer to correct. If your goal is to split a string by Unicode codepoint, this is not the solution for you.

Ky -
  • 30,724
  • 51
  • 192
  • 308
0

As my perspective, The better way with knowing the logic itself is below

 let testStr: String = "I love my family if you Love us to tell us I'm with you"
 var newStr = ""
 let char:Character = "i"

 for value in testStr {
      if value == char {
         newStr = newStr + String(value)
   }

}
print(newStr.count)
Deepak Yadeedya
  • 119
  • 1
  • 12
0
extension String{
    func contains(find: String)->Bool{
        return self.range(of: find) != nil
    }
}
 
func check(n:String, h:String)->Int{
    let n1 = n.lowercased()
    let h1 = h.lowercased()//lowercase to make string case insensitive
    var pos = 0 //postion of substring
    if h1.contains(n1){
       // checking if sub string exists
        if let idx = h1.firstIndex(of:n1.first!){
             let pos1 = h1.distance(from: h1.startIndex, to: idx)
           pos = pos1
        }
        return pos
    }
    else{
        return -1
    }
}
 
print(check(n:"@", h:"hithisispushker,he is 99 a good Boy"))//put substring in n: and string in h
-1

Swift 3

extension String {
        func substring(from:String) -> String
        {
            let searchingString = from
            let rangeOfSearchingString = self.range(of: searchingString)!
            let indexOfSearchingString: Int = self.distance(from: self.startIndex, to: rangeOfSearchingString.upperBound )
            let trimmedString = self.substring(start: indexOfSearchingString , end: self.count)
            
            return trimmedString
        }
        
    }
Community
  • 1
  • 1
Amr Angry
  • 3,711
  • 1
  • 45
  • 37
-1
    // Using Swift 4, the code below works.
    // The problem is that String.index is a struct. Use dot notation to grab the integer part of it that you want: ".encodedOffset"
    let strx = "0123456789ABCDEF"
    let si = strx.index(of: "A")
    let i = si?.encodedOffset       // i will be an Int. You need "?" because it might be nil, no such character found.

    if i != nil {                   // You MUST deal with the optional, unwrap it only if not nil.
        print("i = ",i)
        print("i = ",i!)            // "!" str1ps off "optional" specification (unwraps i).
            // or
        let ii = i!
        print("ii = ",ii)

    }
    // Good luck.
PZX
  • 529
  • 1
  • 4
  • 7