在swift语言中 使用 String 类型定义字符串,例如
let emojiText = "Hello👇👉World🌍🎉"
使用Range截取字符串时会不准确, 👇符合占两个长度, 而在使用emojiText.count 方法中 👇 只占一个长度, 所以需要做特殊处理
String.count:计算的是字符数(grapheme clusters)
NSString.length:计算的是UTF-16码元数
表情符号:有些占用1个UTF-16码元,有些占用2个(如👇)
方法1:使用NSString统一处理(推荐)
import Foundation
func safeSubstringWithEmoji(_ string: String, nsRange: NSRange) -> String? {
let nsString = string as NSString
// 验证NSRange有效性
guard nsRange.location != NSNotFound,
nsRange.location >= 0,
nsRange.length >= 0,
nsRange.location < nsString.length,
nsRange.location + nsRange.length <= nsString.length else {
return nil
}
return nsString.substring(with: nsRange)
}
// 使用示例
let emojiText = "Hello👇👉World🌍🎉"
let ranges = [
NSRange(location: 0, length: 5), // "Hello"
NSRange(location: 5, length: 2), // "👇" (在NSString中占2个UTF-16)
NSRange(location: 7, length: 2), // "👉" (在NSString中占2个UTF-16)
NSRange(location: 9, length: 5), // "World"
NSRange(location: 14, length: 2), // "🌍" (占2个UTF-16)
NSRange(location: 16, length: 2) // "🎉" (占2个UTF-16)
]
for range in ranges {
if let result = safeSubstringWithEmoji(emojiText, nsRange: range) {
print("范围 \(range): '\(result)'")
}
}
获取拼接字符串正确的位置
import Foundation
func appendStringWithEmojiSupport(a: inout String, b: String) -> (result: String, nsRange: NSRange) {
let originalNSLength = (a as NSString).length
a.append(b)
let bNSLength = (b as NSString).length
let range = NSRange(location: originalNSLength, length: bNSLength)
return (a, range)
}
// 使用示例
var emojiText = "Hello👇👉World🌍🎉"
let appendText = " Swift🚀"
let result = appendStringWithEmojiSupport(a: &emojiText, b: appendText)
print("原字符串NSString长度: \((emojiText as NSString).length)")
print("拼接后字符串: '\(result.result)'")
print("B字符串NSRange: \(result.nsRange)")
print("B字符串: '\(appendText)'")
// 验证提取
if let extracted = (result.result as NSString).substring(with: result.nsRange) {
print("验证提取: '\(extracted)'") // 应该输出: " Swift🚀"
}