【问题标题】:How to remove a flag from the end of a string?如何从字符串末尾删除标志?
【发布时间】:2017-01-06 14:57:11
【问题描述】:

我发现函数 String.characters.count 对于其中行是表情符号标志的行有一个奇怪的行为:

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
}

【问题讨论】:

  • 将代码放入问题本身。
  • edit您的问题,而不是在 cmets 中添加代码。谢谢。
  • 感谢 Martin R 的链接,但它不能解决我的问题 :(
  • 我想删除textview中的最后一个字符:text.removeAtIndex(text.endIndex.advancedBy(-1))
  • 如果最后几个符号标志 - 全部删除

标签: swift unicode swift2


【解决方案1】:

Swift 4 (Xcode 9) 更新

从 Swift 4 开始(使用 Xcode 9 beta 测试)标志(即区域对 指标)被视为单个字素簇,如 Unicode 9 标准。所以计数标志并删除最后一个 字符(无论它是否是标志)现在很简单:

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

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

(Swift 3 及更早版本的旧答案:)

没有错误。一系列“区域指示符”字符是 一个单一的“扩展字素簇”,这就是为什么

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

打印1(比较Swift countElements() return incorrect value when count flag emoji)。

另一方面,上面的字符串由 12 个 Unicode 标量组成 (?? 是 ?+ ?),每个都需要两个 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) // ??????????

【讨论】:

  • @ValeryDomozhirov:该问题已在 Swift 4(目前为测试版)中修复,请参阅更新的答案。
【解决方案2】:

@Martin 对 swift3 的回答,有一些修改

注意:我已将扩展转换为函数

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) // ??????????

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-11-05
    • 2017-05-14
    • 2023-04-07
    • 1970-01-01
    • 2011-07-14
    相关资源
    最近更新 更多