2016-08-30 90 views
3

我发现功能String.characters.count一个奇怪的行为在行哪一行是表情符号标志:如何从字符串的末尾删除标志?

import UIKit 

var flag = "" 
print(flag.characters.count) 
print(flag.unicodeScalars.count) 
print(flag.utf16.count) 
print(flag.utf8.count) 
flag = "000" 
print(flag.characters.count) 
print(flag.unicodeScalars.count) 
print(flag.utf16.count) 
print(flag.utf8.count) 

enter image description here

我想限制的文本字符串长度的写作和编辑时在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 
} 
+0

把代码放到这个问题本身。 –

+0

请[edit]您的问题,而不是在评论中添加代码。谢谢。 – Moritz

+0

感谢您的链接马丁R,但它不能解决我的问题:( –

回答

5

更新夫特4(的Xcode 9)

作为夫特4的标志(即,对区域 指标)(在Xcode 9测试版测试)被视为一个单一的字形群集,按照Unicode 9标准 的规定。因此,计数标志和去掉最后 字符(羯羊它是一个标志或没有)现在简单,如:

var flags = "" 
print(flags.count) // 6 

flags.removeLast() 
print(flags.count) // 5 
print(flags) // 

(旧答案斯威夫特3和更早的版本:)

没有错误。的“区域指示符”字符的序列是 一个单一的“扩展字形集群”,这就是为什么

var flag = "" 
print(flag.characters.count) 

打印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?

我没有一个优雅的解决方案(也许有人有一个更好的解决方案)。 但是,一种选择是将字符串分隔成组成字符的数组 ,如有必要,从数组中删除元素, 然后再次组合字符串。

例子:

extension String { 

    func composedCharacters() -> [String] { 
     var result: [String] = [] 
     enumerateSubstringsInRange(characters.indices, options: .ByComposedCharacterSequences) { 
      (subString, _, _, _) in 
      if let s = subString { result.append(s) } 
     } 
     return result 
    } 
} 

var flags = "" 
var chars = flags.composedCharacters() 
print(chars.count) // 6 
chars.removeLast() 
flags = chars.joinWithSeparator("") 
print(flags) // 
+0

谢谢Martin R,它解决了我的问题:) –

+0

@ValeryDomozhirov:该问题已在Swift 4(目前的测试版)中修复,请参阅更新的答案。 –

0

@马丁的答案swift3,有一些修改

注:我已经转换的扩展功能

import Foundation 
func composedCharacters(str:String) -> [String] { 
    var result: [String] = [] 
    str.enumerateSubstrings(in: str.startIndex..<str.endIndex,options: .byComposedCharacterSequences) { 
     (subString, _, _, _) in 
     if let s = subString { result.append(s) } 
    } 
    return result 
} 
var flags = "" 
var chars = composedCharacters(str:flags) 
print(chars.count) // 6 
chars.removeLast() 
flags = chars.joined(separator:"") 
print(flags) //