关于在包含“👇 👉”等特殊emoji表情的字符串中,截取字符串遇到的一些问题

在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🚀"
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容