简单说一下背景,服务端通过 unicode 编码计算出字符串的显示范围,并且将 range 返回给客户端,客户端根据 range,按 unicode 的长度去截取生成对应的字符串。
由于之前的方法不够完善,在用户使用了一些特别的字符,如一些特殊的表情😊,就会出现截取异常的情况,后来将截取方法完善了一下。
基本思路就是使用 string.unicodeScalars,它就是 string 实际对应的 unicode 集合,可以理解成一个数组,然后根据 range 在这个集合中按 index 去截取出对应的子集,再转成 string 即可。
extension String {
/// 取的是将字符串转成unicode编码之后的位置,可以通过string.unicodeScalars拿到字符串对应的unicode编码
/// from < 0 取 0
/// to 越界取string.unicodeScalars的末位
func substringByUnicodeIndex(from: Int, to: Int) -> Self {
let from = from < 0 ? 0 : from
let to = to >= unicodeScalars.count ? unicodeScalars.count :to
guard to >= from else { return self }
let startIndex = unicodeScalars.index(unicodeScalars.startIndex, offsetBy: from)
let endIndex = unicodeScalars.index(unicodeScalars.startIndex, offsetBy: to)
return String(unicodeScalars[startIndex..<endIndex])
}
/// 取的是将字符串转成unicode编码之后的位置和长度,可以通过string.unicodeScalars拿到字符串对应的unicode编码
/// location < 0 取 0
/// location+length 作为末位,如果越界,取string.unicodeScalars的末位
func substringByUnicodeIndex(location: Int, length: Int) -> Self{
let start = location < 0 ? 0 : location
let end = start+length >= unicodeScalars.count ?unicodeScalars.count : start+length
guard end >= start else { return self }
let startIndex = unicodeScalars.index(unicodeScalars.startIndex, offsetBy: start)
let endIndex = unicodeScalars.index(unicodeScalars.startIndex, offsetBy: end)
return String(unicodeScalars[startIndex..<endIndex])
}
}