我发现函数String.characters.count在有Emoji标志的行中有一个奇怪的行为:
import UIKit
var flag = "🇨🇦🇨🇦🇨🇦🇨🇦🇨🇦🇨🇦"
print(flag.characters.count)
print(flag.unicodeScalars.count)
print(flag.utf16.count)
print(flag.utf8.count)
flag = "🇨🇦0🇨🇦0🇨🇦0"
print(flag.characters.count)
print(flag.unicodeScalars.count)
print(flag.utf16.count)
print(flag.utf8.count)
我想在UITextView中编写和编辑时限制文本的字符串长度。实际上我的代码是这样的:
var lastRange: NSRange? = nil
var lastText: String? = nil
func textView(textView: UITextView, shouldChangeTextInRange range: NSRange, replacementText string: String) -> Bool {
if string == "\n" {
// Execute same code
return false
}
var text = string.uppercaseString
if lastText != text || lastRange != nil && (lastRange!.location != range.location || lastRange!.length != range.length) {
lastRange = range
lastText = text
var text = (self.textView.text ?? "" as NSString).stringByReplacingCharactersInRange(range, withString: string)
// Delete chars if length more kMaxLengthText
while text.utf16.count >= kMaxLengthText {
text.removeAtIndex(text.endIndex.advancedBy(-1))
}
// Set position after insert text
self.textView.selectedRange = NSRange(location: range.location + lastText!.utf16.count, length: 0)
}
return false
}
2条答案
按热度按时间wwwo4jvm1#
针对Swift 4(Xcode 9)的更新
从Swift 4开始(用Xcode 9测试),标志(即成对的区域指示符)被视为一个单一的字形簇,这是Unicode 9标准所要求的。因此,计数标志并删除最后一个字符(无论它是不是标志)现在就像这样简单:
没有bug。一个“区域指示符”字符序列是一个单一的“扩展字素簇”,这就是为什么
打印
1
(比较Swift countElements() return incorrect value when count flag emoji)。另一方面,上面的字符串由12个Unicode标量(🇨🇦is🇨+🇦)组成,每个标量都需要两个UTF-16码位。
要将字符串分离成“可见实体”,您必须考虑“组合字符序列”,请比较How to know if two emojis will be displayed as one emoji?。
我没有一个优雅的解决方案(也许有人有更好的解决方案),但有一个选择是将字符串分成一个由字符组成的数组,如果需要,从数组中删除元素,然后再次合并字符串。
示例:
thtygnil2#
@马丁对swift 3的回答,有一些修改
注意:我已将扩展转换为函数