Swift4ではsubstring()がdeprecatedになっているようで警告が出るのでSiwft4での適正な方法を調べました。SwiftではバージョンアップのたびにStringのような基本データ型の操作方法が変わってどんどんノウハウが古くなるので困ります。しかもString型のリファレンスでは掲載されていないし、リファレンス見ただけではぱっとみ分からず困った物です。

□先頭からn文字


・先頭からn文字分を切り出す場合には prefix() を使うのが簡単。ただし、リターン値の型はSubstring (String.SubSequence) なので、文字列として使う場合にはStringにキャストする必要があるかもしれない。
let str = "0123456789"
str.prefix(5) // "01234" 



・範囲を指定してサブスクリプトを使って切り出す。この時、範囲は整数値で指定するのではなく、String.Index型であることを注意する。
let str = "0123456789"
str[..<str.index(str.startIndex, offsetBy: 5)] // "01234" 


□末尾までのn文字


・末尾までのn文字を切り出す場合には、 suffix() を使うのが簡単。整数で指定可能。
let str = "0123456789"
str.suffix(5) // "56789" 


・範囲を指定してサブスクリプトを使って切り出す。
let str = "0123456789"
number[number.index(number.endIndex, offsetBy: -5)...] // "56789" 


□n文字目からm文字


・例えば5文字目から3文字切り出すには、5文字目を示すString.Indexを作り、そのIndexを起点に+3のIndexを作り終点とする。始点はオフセットとしてn-1を指定する。切り出すのは5文字目・6文字目・7文字目だけど終点は8文字目を指している。範囲を指定するときに終端を含まないようにするので問題ない。

let str = "0123456789"
let start = number.index(str.startIndex, offsetBy: 4)
let end = number.index(start, offsetBy: 3)
number[start..<end] // "456" ← こっち
number[start...end] // "4567"


□先頭からある文字より前の文字


・Characterを指定して検索する。その文字を含んでいない場合にはnilになるので、対応が必要。以下は単純にunwrapしているだけ。prefixでも可。
let name = "filename.ext"
let idx = name.index(of: ".")
name[..<idx!] // "filename"
name.prefix(upTo: idx!)


・文字列を指定する場合にはRangeになるので下限から。
let idx = str.range(of: ",")?.lowerBound
name[..<idx!] // "filename"


□ある文字より後ろの文字列を末尾まで


・検索で見つけた文字の次の文字から取り出したいので、インデックスを1つ後ろに進める必要がある。suffix() も可能。

let name = "filename.ext"
let idx1 = name.index(of: ".")
let idx2 = name.index(after:idx1!)
name[idx2!...] // "ext"
name.suffix(from: idx2!) ) //  "ext"


□ある文字と別のある文字に挟まれた文字

・ある文字から別の文字までの範囲の文字列を取り出す場合(検索文字含む場合)
let str = "This is a <strong>red circle."
let idx1 = str.index(of: "<")
let subs = str.suffix(from: idx3!)
let idx2 = subs.index(of: ">")
str[idx1!...idx2!] // "<strong>"


・検索文字を含まない場合には、先頭を index(after:)で1つ進める。終端は範囲指定の終端を含まないで示すので操作しなくてもよい。
let str = "This is a <strong>red</strong> circle."
let idx1 = str.index(after:str.index(of: "<")!)
let subs = str.suffix(from: idx3!)
let idx2 = subs.index(of: ">")
str[idx1..<idx2!] // "strong"

□番外編:ある文字が登場するのは何文字目か?

・ある文字を検索してその文字が登場するのが何文字目かを整数値で示すには、先頭からカウントするしかないようだ。
let str = "0123456789"
extension String {
    func position(of chr:Character) -> Int {
        let stopIndex = self.index(of: chr)
        var index = self.startIndex
        var pos = 0
        while index != stopIndex  {
            index = self.index(after: index)
            pos += 1
        }
        return pos
    }
}
str.position(of:"3") // 3 : 0始まり


注)自宅の開発環境をすべてSwift4に統一しました。今後はできる限りSwift4で開発していきます。