Berikut adalah ekstensi yang memungkinkan Anda mengakses batas substring sebagai Ints, bukan String.Indexnilai:
import Foundation
extension StringProtocol {
func countableRange<SearchType: StringProtocol>(
of search: SearchType,
options: String.CompareOptions = [],
range: Range<String.Index>? = nil,
locale: Locale? = nil
) -> CountableRange<Int>? {
guard let trueRange = self.range(of: search, options: options, range: range, locale: locale) else {
return nil
}
let intStart = self.distance(from: startIndex, to: trueRange.lowerBound)
let intEnd = self.distance(from: trueRange.lowerBound, to: trueRange.upperBound) + intStart
return Range(uncheckedBounds: (lower: intStart, upper: intEnd))
}
}
Sadarilah bahwa ini dapat menyebabkan keanehan, itulah sebabnya Apple memilih untuk membuatnya sulit. (Meskipun itu adalah keputusan desain yang bisa diperdebatkan - menyembunyikan hal yang berbahaya hanya dengan membuatnya sulit ...)
Anda dapat membaca lebih lanjut di dokumentasi String dari Apple , tetapi tldrnya adalah bahwa ini berasal dari fakta bahwa "indeks" ini sebenarnya khusus untuk penerapan. Mereka mewakili indeks ke dalam string setelah dirender oleh OS , dan dengan demikian dapat bergeser dari OS-ke-OS tergantung pada versi apa dari spesifikasi Unicode yang digunakan. Ini berarti bahwa mengakses nilai dengan indeks tidak lagi menjadi operasi waktu konstan, karena spesifikasi UTF harus dijalankan di atas data untuk menentukan tempat yang tepat dalam string. Indeks ini juga tidak akan sejalan dengan nilai yang dihasilkan oleh NSString, jika Anda menjembataninya, atau dengan indeks ke skalar UTF yang mendasarinya. Pengembang peringatan.