●Swiftのinsertはなぜこんなにめんどいのか
Swiftで文字列の任意の位置にinsert
したい時って、こんな感じに結構めんどい。
先頭からとか末尾からとか考えるのも結構めんどい。
var str = "HelloWorld"
// 先頭から1文字目と2文字目の間に文字列を挿入
str.insert("★", at: str.index(str.startIndex, offsetBy: 1)) // H★elloWorld
// 末尾から5文字目と6文字目の間に文字列を挿入
str.insert("★", at: str.index(str.endIndex, offsetBy: -5)) // Hello★World
しかもターゲットの文字列の範囲外のindexを指定した場合は、クラッシュする。
var str = "HelloWorld"
// 先頭から1文字目と2文字目の間に文字列を挿入
str.insert("★", at: str.index(str.startIndex, offsetBy: 11))
// → error: Execution was interrupted, reason: EXC_BREAKPOINT
●メンドいことは Extension で解決しよう
下記のようにString
型のExtension
を作ってみると結構便利になる。
import Foundation
extension String {
enum InsertFrom {
case front
case back
}
func insert(_ str: String, at index: Int, from direction: InsertFrom) -> String {
if self.count < index { return self }
let firstIndex = direction == .front ? index : self.count - index
let secondIndex = direction == .front ? self.count - index : index
return prefixString(firstIndex) + str + suffixString(secondIndex)
}
}
extension String {
func prefixString(_ index: Int) -> String {
return String(self.prefix(index))
}
func suffixString(_ index: Int) -> String {
return String(self.suffix(index))
}
}
●Point
at index: Int
→ 挿入したい位置をindex指定する
from direction: InsertFrom
→ indexを先頭or末尾、どちらから指定するかenumInsertFrom
を指定する
if self.count < index { return self }
→ 範囲外のindexを指定した場合は文字列をそのままreturnし、クラッシュ回避
prefixString
suffixString
→prefix
suffix
の返り値がSubstring
でダルいので
これもStringを返すようにExtensionしちゃう
●使うとこんな感じ
var str = "HelloWorld"
// 先頭から1文字目と2文字目の間に文字列を挿入
let result1 = str.insert("★", at: 1, from: .front) // H★elloWorld
// 末尾から5文字目と6文字目の間に文字列を挿入
let result2 = str.insert("★", at: 5, from: .back) // Hello★World
クラッシュもしない
var str = "HelloWorld"
// 範囲外のindexに文字列を挿入
let result = str.insert("★", at: 11, from: .front) // HelloWorld
外部引数のおかげで より英文的 に呼び出せるのも結構気に入ってる。
Insert string at third from front.
みたいにね。
他にも何かExtension思いついたら投稿しようと思います✌️