Masalah: NSAttributedString mengambil NSRange saat saya menggunakan Swift String yang menggunakan Range
let text = "Long paragraph saying something goes here!"
let textRange = text.startIndex..<text.endIndex
let attributedString = NSMutableAttributedString(string: text)
text.enumerateSubstringsInRange(textRange, options: NSStringEnumerationOptions.ByWords, { (substring, substringRange, enclosingRange, stop) -> () in
if (substring == "saying") {
attributedString.addAttribute(NSForegroundColorAttributeName, value: NSColor.redColor(), range: substringRange)
}
})
Menghasilkan kesalahan berikut:
galat: 'Rentang' tidak dapat dikonversi menjadi 'NSRange' yang dikaitkanString.addAttribute (NSForegroundColorAttributeName, nilai: NSColor.redColor (), rentang: substringRange)
Jawaban:
Swift
String
rentang danNSString
rentang tidak "kompatibel". Misalnya, emoji seperti π dihitung sebagai satu karakter Swift, tetapi sebagai duaNSString
karakter (pasangan pengganti UTF-16).Karena itu solusi yang Anda sarankan akan menghasilkan hasil yang tidak terduga jika string berisi karakter tersebut. Contoh:
Keluaran:
Seperti yang Anda lihat, "ph say" telah ditandai dengan atribut, bukan "mengatakan".
Karena
NS(Mutable)AttributedString
pada akhirnya membutuhkanNSString
danNSRange
, sebenarnya lebih baik untuk mengubah string yang diberikanNSString
terlebih dahulu. Maka itusubstringRange
adalahNSRange
dan Anda tidak perlu mengonversi rentang lagi:Keluaran:
Pembaruan untuk Swift 2:
Pembaruan untuk Swift 3:
Pembaruan untuk Swift 4:
Pada Swift 4 (Xcode 9), perpustakaan standar Swift menyediakan metode untuk mengkonversi antara
Range<String.Index>
danNSRange
. Konversi keNSString
tidak lagi diperlukan:Berikut
substringRange
ini adalahRange<String.Index>
, dan yang dikonversi ke sesuaiNSRange
dengansumber
Range<String.Index>
danNSString
tidak kompatibel. Apakah mitra mereka juga tidak kompatibel? YaituNSRange
danString
tidak kompatibel? Karena salah satu API Apple secara khusus menggabungkan dua: kecocokan (dalam: opsi: kisaran :)Untuk kasus-kasus seperti yang Anda gambarkan, saya menemukan ini berfungsi. Ini relatif pendek dan manis:
sumber
NSRange
.str
adalahNSString
dan karenanyastr.RangeOfString()
mengembalikan sebuahNSRange
.let str = attributedString.string as NSString
Jawabannya baik-baik saja, tetapi dengan Swift 4 Anda dapat menyederhanakan kode Anda sedikit:
Berhati-hatilah, karena
range
fungsi harus dibuka.sumber
Kemungkinan Solusi
Swift menyediakan jarak () yang mengukur jarak antara mulai dan akhir yang dapat digunakan untuk membuat NSRange:
sumber
Bagi saya ini berfungsi dengan baik:
sumber
Swift 4:
Tentu, saya tahu Swift 4 sudah memiliki ekstensi untuk NSRange
Saya tahu dalam banyak kasus init ini sudah cukup. Lihat penggunaannya:
Tetapi konversi dapat dilakukan langsung dari Range <String.Index> ke NSRange tanpa instance String Swift.
Alih-alih penggunaan init umum yang mengharuskan dari Anda parameter target sebagai String dan jika Anda tidak memiliki string target , Anda dapat membuat konversi secara langsung
atau Anda dapat membuat ekstensi khusus untuk Range itu sendiri
Pemakaian:
atau
Swift 5:
Karena migrasi string Swift ke pengkodean UTF-8 secara default, penggunaan
encodedOffset
dianggap usang dan Rentang tidak dapat dikonversi ke NSRange tanpa instance dari String itu sendiri, karena untuk menghitung offset kita perlu string sumber yang dikodekan dalam UTF-8 dan harus dikonversi ke UTF-16 sebelum menghitung offset. Jadi pendekatan terbaik, untuk saat ini, adalah dengan menggunakan init generik .sumber
encodedOffset
yang dianggap berbahaya dan akan ditinggalkan .Cepat 4
Saya pikir, ada dua cara.
1. NSRange (rentang, dalam:)
2. NSRange (lokasi :, panjang:)
Kode sampel:
Tangkapan Layar:
sumber
encodedOffset
yang dianggap berbahaya dan akan ditinggalkan .Swift 3 Extension Variant yang mempertahankan atribut yang ada.
sumber
sumber
Saya suka bahasa Swift, tetapi menggunakan
NSAttributedString
dengan SwiftRange
yang tidak kompatibel denganNSRange
telah membuat kepala saya sakit terlalu lama. Jadi untuk mengatasi semua sampah itu saya merancang metode berikut untuk mengembalikan sebuahNSMutableAttributedString
dengan kata-kata yang disorot diatur dengan warna Anda.Ini tidak berfungsi untuk emoji. Ubah jika Anda harus.
Pemakaian:
sumber
sumber