在Swift中将布尔值转换为整数值

44

我正在从Swift 2转换到Swift 3。 我注意到在Swift 3中无法将布尔值转换为整数值。

let p1 = ("a" == "a") //true

print(true)           //"true\n"
print(p1)             //"true\n"

Int(true)             //1

Int(p1)               //error
例如,在Swift 2中,这些语法是有效的。但在Swift 3中,print(p1)会产生错误。 错误是error: cannot invoke initializer for type 'Int' with an argument list of type '((Bool))' 我理解为什么会出现这些错误。有人能解释一下这种安全性的原因以及如何在Swift 3中将布尔值转换为整数吗?

1
对于Swift 4,请参见我的已接受的答案以获取类似问题的解决方案。 - Imanou Petit
9个回答

73

你可以使用三元运算符将一个布尔值转换为整数:

let result = condition ? 1 : 0

result如果condition为真,则为1;如果condition为假,则为0。


3
在Swift 3中,将布尔值转换为整数值是不可行的? - Shubhashis
3
我不相信这种转换真的是 Swift 的一部分。我认为它是通过 NSNumber 隐式转换的副作用。在 C 中,隐式的 Bool/Int 转换是旧缺陷的来源(特别是因为非零数如“2”是 “类似 true” 但不等于 true)。Swift 已经积极努力避免这些历史性缺陷的来源。 - Rob Napier

65

Swift 5

布尔类型 -> 整数类型

extension Bool {
    var intValue: Int {
        return self ? 1 : 0
    }
}
转换为 。
extension Int {
    var boolValue: Bool {
        return self != 0 
    }
}

2
抢先一步了!这绝对是我首选的解决方案。它比其他方案更符合Swift的规范。 - user3225395
而要走相反的方向(Int -> Bool)https://dev59.com/flkS5IYBdhLWcg3wUFB0#45008003 - mikebob
从没想过以这种方式解决它。这很不错。就像 NSNumber 一样工作。 - Baran Emre
太棒了,伙计。你刚刚帮我省了不少时间和烦恼 :) - ibyte

21

试一试这个。

let p1 = ("a" == "a") //true
print(true)           //"true\n"
print(p1)             //"true\n"

Int(true)             //1

Int(NSNumber(value:p1)) //1

3
似乎已经过时。 - user5306470

13

编辑 - 根据评论中的交流,越来越清楚地表明下面第二种方法(Int.init重载)更符合Swift的发展方向。

或者,如果这是您在应用程序中经常进行的操作,则可以创建一个协议,并使用它扩展需要转换为Int的每个类型。

extension Bool: IntValue {
    func intValue() -> Int {
        if self {
            return 1
        }
        return 0
    }
}

protocol IntValue {
    func intValue() -> Int
}

print("\(true.intValue())") //prints "1"

编辑-为了涵盖Rob Napier在下面评论中提到的情况示例,可以像这样做:

extension Int {
    init(_ bool:Bool) {
        self = bool ? 1 : 0
    }
}

let myBool = true
print("Integer value of \(myBool) is \(Int(myBool)).")

或者将 @eric-aya 的三元操作建议与最大简洁性的协议相结合! - diatrevolo
1
这种方法通常被Swift核心团队不鼓励。他们建议使用Int.init重载而不是方法来执行全宽度转换。 - Rob Napier
有没有相关的文档可以阅读,@Rob-napier?我想了解更多为什么不鼓励这样做以及导致该决定的讨论。 - diatrevolo
我现在找不到相关的讨论,可能被埋在了Swift-evo的某个地方。但是你可以通过观察stdlib的演变来看出这种意见的结果。例如,查看https://github.com/apple/swift-evolution/blob/master/proposals/0006-apply-api-guidelines-to-the-standard-library.md,并注意`...value`方法已经转换为`init`(虽然stdlib中从来没有太多的`...value`方法,但请参见`ObjectIdentifier`和`StaticString`)。此外,在Swift 3风格指南中,类型转换只讨论了init,而不是方法。 - Rob Napier
很酷,更多的是好奇。谢谢! - diatrevolo
我希望我能找到一个特定的“这是历史记录”的东西,但更多的是“每次我在LazySequence上使用.array替换Array.init时,团队中的某个人都会提醒我更喜欢使用init”。 - Rob Napier

5

Swift 5.4

这是一种更通用的方法,适用于除 Int 外的其他类型。

extension ExpressibleByIntegerLiteral {
    init(_ booleanLiteral: BooleanLiteralType) {
        self = booleanLiteral ? 1 : 0
    }
}

let bool1 = true
let bool2 = false

let myInt = Int(bool1) // 1
let myFloat = Float(bool1) // 1
let myDouble = Double(bool2) // 0
let myCGFloat = CGFloat(bool2) // 0

1
你可以使用 hashValue 属性:
let active = true
active.hashValue // returns 1
active = false
active.hashValue // returns 0

13
如果你在Swift 4.2中这样做,你会得到类似于482808648934333090的数值。 - Jadekin
是的,您可以查看这个问答 https://dev59.com/Ga7la4cB1Zd3GeqPWxI_ - Ahmet Sina Ustem

1

unsafeBitCast总是一种选择

let int: Int = Int(unsafeBitCast(someBool, to: UInt8.self))

1
在 Stack Overflow,提供解释总是有用的,但特别重要的是当问题已经得到社区满意解答时。通过解释您的答案与众不同之处以及何时可能更受青睐来帮助读者。您可以编辑您的问题以添加更多细节吗? - Jeremy Caney
那似乎不安全。 - clearlight

0

已在Swift 3.2和Swift 4中进行了测试

不需要将其转换为Int

尝试这个 -

let p1 = ("a" == "a") //true

print(true)           //"true\n"
print(p1)             //"true\n"

Int(true)             //1

print(NSNumber(value: p1))   

0
在 Swift 5 中:
你可以这样做:
let x = ("a" == "a")

Int(truncating: x as NSNumber)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接