解决 swift 下截取表情字符串异常的问题

874 阅读1分钟

简单说一下背景,服务端通过 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(fromInttoInt) -> 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(locationIntlengthInt) -> 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])
   }
}