NSString 的 `boolValue` 方法的精确 Swift 替代?

问题描述 投票:0回答:1

有多个线程讨论如何复制 NSString 的

boolValue
方法,但大多数都是猜测或简化。

Apple 只给了我们这个简短的描述:

遇到“Y”、“y”、“T”、“t”或数字 1-9 之一时,此属性为 YES — 该方法忽略任何尾随字符。如果接收者不以数字的有效十进制文本表示形式开始,则此属性为“否”。 该属性采用十进制表示形式并跳过字符串开头的空格。它还会跳过初始空白字符或可选的 -/+ 符号后跟零。

那么它认为什么是空白呢? “采用十进制表示”是什么意思?

我正在转换现有的 Objective-C 应用程序并将其转换为 Swift,并且想要一个真正的 Swift

boolValue
方法,而无需先将字符串转换为 NSString(即
(string as NSString).boolValue()

swift nsstring boolvalue
1个回答
0
投票

事实证明,Apple 的简洁描述是完整且正确的!空白是 null、空格和制表符的集合。 “0”的运行可以选择添加“+”或“-”前缀。

这个 Swift 代码完全复制了 NSString 函数(至少对于 ASCII 来说

extension String {

var boolValue: Bool {
    guard !self.isEmpty else { return false }

    // NSString treats these as "false"  "\u{000A}", "\u{000B}", "\u{000C}", "\u{000D}",
    let whiteSpace: Set<Character>  = ["\u{0000}", "\u{0009}", "\u{0020}" ]
    let trueChar: Set<Character>    = ["t", "T", "y", "Y", "1", "2", "3", "4", "5", "6", "7", "8", "9"]
    let trueNum: Set<Character>     = ["1", "2", "3", "4", "5", "6", "7", "8", "9"]
    let zeroRun: Set<Character>     = ["+", "-", "0"]

    var index = self.startIndex
    let lastIndex = self.endIndex

    var c: Character
    repeat {
        c = self[index]
        index = self.index(index, offsetBy: 1)
    } while whiteSpace.contains(c) && index < lastIndex; // up to the last character

    if zeroRun.contains(c) && index < lastIndex {
        repeat {
            c = self[index]
            index = self.index(index, offsetBy: 1)
        } while c == "0" && index < lastIndex; // up to the last character
        return trueNum.contains(c)
    } else {
        return trueChar.contains(c)
    }
}

}

我可以声称兼容性的原因是,我创建了一个测试工具来将上述代码与 NSString

boolValue
方法进行比较,并确保两者使用以下代码为 1,000,000,000 个“模糊”测试返回相同的值:

func test() {
    func random() -> String {
        let val = Int.random(in: 0..<128)
        let c = String(format: "%c", val)

        return c
    }
    
    var i = 0
    while true {
        var s = ""
        let len = Int.random(in: 1..<16)
        for _ in 0..<len {
            s += random()
        }

        let oTest = (s as NSString).boolValue
        let sTest = s.boolValue
        if oTest != sTest {
            print("Testing \(s) oTest=\(oTest) sTest=\(sTest)")
            for c in s {
                print("HEX:", String(format: "%2.2X char=%c", c.asciiValue!), c)
            }

            var str = "\""
            for c in s {
                str += String(format: "\\u{%4.4X}", c.asciiValue!)
            }
            str += "\""
            print(str)
            fatalError()
        }

        i += 1
        if i % 1_000_000 == 0 {
            print("Count \(i)")
            if i == 1_000_000_000 {
                break
            } else {
                sleep(1)
            }
        }
    }
}

请注意,字符串包含 ASCII 0 到 127 范围内的随机字符。

当然,我的编码失败了好几次才得到正确的结果!

© www.soinside.com 2019 - 2024. All rights reserved.