Converting Boolean value to Integer value in Swift
Asked Answered
Y

10

44

I was converting from Swift 2 to Swift 3. I noticed that I cannot convert a boolean value to integer value in Swift 3.

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

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

Int(true)             //1

Int(p1)               //error

For example these syntaxes worked fine in Swift 2. But in Swift 3, print(p1) yields an error.

The error is error: cannot invoke initializer for type 'Int' with an argument list of type '((Bool))'

I understand why the errors are happening. Can anyone explain what is the reason for this safety and how to convert from Bool to Int in Swift 3?

Yarkand answered 25/10, 2016 at 14:29 Comment(1)
For Swift 4, see my accepted answer for a similar question.Kosse
B
66

Swift 5

Bool -> Int

extension Bool {
    var intValue: Int {
        return self ? 1 : 0
    }
}

Int -> Bool

extension Int {
    var boolValue: Bool {
        return self != 0 
    }
}
Ballinger answered 5/9, 2017 at 14:21 Comment(4)
Beat me to it! This is definitely my preferred solution. It adheres to Swift conventions more than other solutions here.Chigetai
And to go in the opposite direction (Int -> Bool) https://mcmap.net/q/374822/-converting-int-to-boolIndiscernible
Never thought to solve it this way. This is quite good. Works like NSNumber.Rout
Amazing mate. You have just saved me some time and head-scratching :)Turkoman
E
74

You could use the ternary operator to convert a Bool to Int:

let result = condition ? 1 : 0

result will be 1 if condition is true, 0 is condition is false.

Edo answered 25/10, 2016 at 14:38 Comment(2)
Ok, so casting from Boolean to Integer value is a no go in swift 3?Yarkand
I don't believe this conversion was really ever part of Swift. I believe it was a side-effect of implicit conversions through NSNumber. Implicit Bool/Int conversions are an old source of bugs in C (in particular, because non-zero numbers like "2" is "true-ish" but not equal to true). Swift has actively tried to avoid these historic sources of bugs.Hawser
B
66

Swift 5

Bool -> Int

extension Bool {
    var intValue: Int {
        return self ? 1 : 0
    }
}

Int -> Bool

extension Int {
    var boolValue: Bool {
        return self != 0 
    }
}
Ballinger answered 5/9, 2017 at 14:21 Comment(4)
Beat me to it! This is definitely my preferred solution. It adheres to Swift conventions more than other solutions here.Chigetai
And to go in the opposite direction (Int -> Bool) https://mcmap.net/q/374822/-converting-int-to-boolIndiscernible
Never thought to solve it this way. This is quite good. Works like NSNumber.Rout
Amazing mate. You have just saved me some time and head-scratching :)Turkoman
C
21

Try this,

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

Int(true)             //1

Int(NSNumber(value:p1)) //1
Cryptomeria answered 25/10, 2016 at 16:54 Comment(1)
Seems deprecatedJasper
K
13

EDIT - From conversations in the comments, it is becoming clearer that the second way of doing this below (Int.init overload) is more in the style of where Swift is headed.

Alternatively, if this were something you were doing a lot of in your app, you could create a protocol and extend each type you need to convert to Int with it.

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

protocol IntValue {
    func intValue() -> Int
}

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

EDIT- To cover an example of the case mentioned by Rob Napier in the comments below, one could do something like this:

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

let myBool = true
print("Integer value of \(myBool) is \(Int(myBool)).")
Katmandu answered 25/10, 2016 at 14:54 Comment(6)
Or combine @eric-aya 's ternary op recommendation with a protocol for maximum conciseness!Katmandu
This approach has generally been discouraged by the core Swift team. They recommend Int.init overloads rather than methods to perform full-width conversions.Hawser
Any documentation I could read to that effect @Rob-napier? I'd like to know more about why it's discouraged and the discussion leading to that decision.Katmandu
I can't put my hands on a conversation right now; buried somewhere in swift-evo. But you can see the results of the opinion by watching how stdlib has evolved. For example, see github.com/apple/swift-evolution/blob/master/proposals/… and note where ...value methods have been converted to init (there were never many ...value methods in stdlib, but see ObjectIdentifier and StaticString). Note also in the Swift 3 style guidelines that type conversions are only discussed in terms of init's. Never methods.Hawser
Cool, more curious than anything. Thanks!Katmandu
I wish I could put my hands on a specific "here is the history," but it's much more "every time I bring up .array on LazySequence to replace Array.init, I'm reminded by one of the team that there is a preference for init.Hawser
P
5

Swift 5.4

This is a more generic approach which is applicable for other types than just 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
Postliminy answered 21/6, 2021 at 14:8 Comment(0)
M
2

unsafeBitCast is always an option

let int: Int = Int(unsafeBitCast(someBool, to: UInt8.self))
Manhandle answered 31/12, 2021 at 1:4 Comment(2)
Offering an explanation is always useful on Stack Overflow, but it's especially important where the question has been resolved to the satisfaction of the community. Help readers out by explaining what your answer does different and when it might be preferred. Can you edit your question to add more detail?Concertina
That doesn't seem safeInwardness
G
0

You could use hashValue property:

let active = true
active.hashValue // returns 1
active = false
active.hashValue // returns 0
Gipon answered 25/8, 2017 at 11:54 Comment(2)
If you do this in Swift 4.2, you are going to get values like 482808648934333090 and similar.Everyplace
Yes, you can look at this Q&A https://mcmap.net/q/374823/-bool-hashvalue-valid-to-convert-to-int/4711785Bulk
M
0

Tested in swift 3.2 and swift 4

There is not need to convert it into Int

Try this -

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

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

Int(true)             //1

print(NSNumber(value: p1))   
Mayan answered 30/8, 2018 at 15:17 Comment(0)
S
0

In swift 5:

you can do this:

let x = ("a" == "a")

Int(truncating: x as NSNumber)
Schist answered 11/4, 2023 at 10:43 Comment(0)
B
0

This is my preferred adaptation of existing solutions, just an overload of Int. This way I don't have to remember any additional syntax.

func Int(_ boolean: Bool) -> Int {
    boolean ? 1 : 0
}
Biliary answered 14/3, 2024 at 2:20 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.