NSCharacterSet.characterIsMember()与Swift的字符类型

时间:2014-12-29 23:27:25

标签: swift

想象一下,您有一个Swift的Character类型的实例,并且您想确定它是否是NSCharacterSet的成员。 NSCharacterSet characterIsMember方法需要unichar,因此我们需要从Characterunichar

我能提出的唯一解决方案如下:cCharacter

let u: unichar = ("\(c)" as NSString).characterAtIndex(0)
if characterSet.characterIsMember(u) {
    dude.abide()
}

我看了Character,但没有任何事情从我身上跳过,作为从unichar开始的方式。这可能是因为Characterunichar更通用,所以直接转换不安全,但我只是在猜测。

如果我正在迭代整个字符串,我会做这样的事情:

let s = myString as NSString
for i in 0..<countElements(myString) {
    let u = s.characterAtIndex(i)
    if characterSet.characterIsMember(u) {
        dude.abide()
    }
}

(警告:上面是伪代码,从来没有人经营过。)但这并不是我所要求的。

5 个答案:

答案 0 :(得分:22)

我的理解是unicharUInt16的类型。 unichar只是一个数字。

我认为你面临的问题是Swift中的Character可以由多个unicode“字符”组成。因此,它不能转换为单个unichar值,因为它可能由两个unichars组成。您可以将Character分解为单个unichar值,方法是将其转换为字符串并使用utf16属性,如下所示:

let c: Character = "a"
let s = String(c)
var codeUnits = [unichar]()
for codeUnit in s.utf16 {
    codeUnits.append(codeUnit)
}

这将生成一个数组 - codeUnits - unichar个值。

编辑:初始代码应为for codeUnit in s

时为for codeUnit in s.utf16

你可以整理一下并测试每个unichar值是否在这样的字符集中:

let char: Character = "\u{63}\u{20dd}" // This is a 'c' inside of an enclosing circle
for codeUnit in String(char).utf16 {
    if NSCharacterSet(charactersInString: "c").characterIsMember(codeUnit) {
        dude.abide()
    } // dude will abide() for codeUnits[0] = "c", but not for codeUnits[1] = 0x20dd (the enclosing circle)
}

或者,如果您只对第一个(通常只有)unichar值感兴趣:

if NSCharacterSet(charactersInString: "c").characterIsMember(String(char).utf16[0]) {
    dude.abide()
}

或者,将其包装在一个函数中:

func isChar(char: Character, inSet set: NSCharacterSet) -> Bool {
    return set.characterIsMember(String(char).utf16[0])
}

let xSet = NSCharacterSet(charactersInString: "x")
isChar("x", inSet: xSet)  // This returns true
isChar("y", inSet: xSet)  // This returns false

现在让函数检查组合字符中所有 unichar的值 - 这样,如果你有一个组合字符,那么只有基本字符和组合字符存在:

func isChar(char: Character, inSet set: NSCharacterSet) -> Bool {
    var found = true
    for ch in String(char).utf16 {
        if !set.characterIsMember(ch) { found = false }
    }
    return found
}

let acuteA: Character = "\u{e1}"                   // An "a" with an accent
let acuteAComposed: Character = "\u{61}\u{301}"    // Also an "a" with an accent

// A character set that includes both the composed and uncomposed unichar values
let charSet = NSCharacterSet(charactersInString: "\u{61}\u{301}\u{e1}")

isChar(acuteA, inSet: charSet)           // returns true
isChar(acuteAComposed, inSet: charSet)   // returns true (both unichar values were matched

最后一个版本很重要。如果你的Character是一个组合字符,你必须检查字符集中是否存在基本字符(“a”)和组合字符(急性重音),否则你会得到误报。

答案 1 :(得分:12)

我会将角色视为一个字符串,并让Cocoa完成所有工作:

func charset(cset:NSCharacterSet, containsCharacter c:Character) -> Bool {
    let s = String(c)
    let ix = s.startIndex
    let ix2 = s.endIndex
    let result = s.rangeOfCharacterFromSet(cset, options: nil, range: ix..<ix2)
    return result != nil
}

以下是如何使用它:

let cset = NSCharacterSet.lowercaseLetterCharacterSet()
let c : Character = "c"
let ok = charset(cset, containsCharacter:c) // true

答案 2 :(得分:4)

在一个班轮中完成所有工作:

validCharacterSet.contains(String(char).unicodeScalars.first!)

(斯威夫特3)

答案 3 :(得分:2)

由于Swift 3.0的变化,亚马特的答案不再适用,所以这里是工作版(作为扩展名):

private extension NSCharacterSet {

  func containsCharacter(c: Character) -> Bool {

       let s = String(c)
       let ix = s.startIndex
       let ix2 = s.endIndex
       let result = s.rangeOfCharacter(from: self as CharacterSet, options: [], range: ix..<ix2)
       return result != nil
  }
}

答案 4 :(得分:0)

Swift 3.0更改意味着您实际上不再需要桥接到NSCharacterSet,您可以使用Swift的原生CharacterSet

你可以直接做一些类似于Jiri的回答:

extension CharacterSet {
    func contains(_ character: Character) -> Bool {
        let string = String(character)
        return string.rangeOfCharacter(from: self, options: [], range: string.startIndex..<string.endIndex) != nil
    }
}

或做:

func contains(_ character: Character) -> Bool {
    let otherSet = CharacterSet(charactersIn: String(character))
    return self.isSuperset(of: otherSet)
}

注意:由于https://bugs.swift.org/browse/SR-3667,上述崩溃并不起作用。不确定CharacterSet会得到它所需要的那种爱。