63

Given a Bool?, I'd like to be able to do this:

let a = BoolToString(optbool) ?? "<None>"

which would either give me "true", "false", or "<None>".

Is there a built-in for BoolToString?

6 Answers6

74

String(Bool) is the easiest way.

var myBool = true
var boolAsString = String(myBool)
60
let b1: Bool? = true
let b2: Bool? = false
let b3: Bool? = nil

print(b1?.description ?? "none") // "true"
print(b2?.description ?? "none") // "false"
print(b3?.description ?? "none") // "none"

or you can define 'one liner' which works with both Bool and Bool? as a function

func BoolToString(b: Bool?)->String { return b?.description ?? "<None>"}
user3441734
  • 16,722
  • 2
  • 40
  • 59
  • 1
    Change `"none"` to `""`. I think we have a winner here! :-) – vacawama Nov 22 '15 at 22:27
  • That's not quite orthodox Swift programming, the conventions of conversion via type initializers is one of prominent feature of all data conversion APIs. However, `CustomStringConvertible`, which declares `description` is an API that semantically is supposed to be used not for data serialization but debugging purposes. You should always use String.init(_:) instead. – Isaaс Weisberg Aug 09 '21 at 13:02
  • @IsaaсWeisberg is certainly right. The documentation for `description` discourages calling it directly. https://developer.apple.com/documentation/swift/customstringconvertible – Patrick Feb 14 '22 at 15:01
24
let trueString = String(true) //"true"
let trueBool = Bool("true")   //true
let falseBool = Bool("false") //false
let nilBool = Bool("foo")     //nil
Elijah
  • 8,381
  • 2
  • 55
  • 49
7

You could use the ?: ternary operator:

let a = optBool == nil ? "<None>" : "\(optBool!)"

Or you could use map:

let a = optBool.map { "\($0)" } ?? "<None>"

Of the two, optBool.map { "\($0)" } does exactly what you want BoolToString to do; it returns a String? that is Optional(true), Optional(false), or nil. Then the nil coalescing operator ?? unwraps that or replaces nil with "<None>".

Update:

This can also be written as:

let a = optBool.map(String.init) ?? "<None>"

or:

let a = optBool.map { String($0) } ?? "<None>"
vacawama
  • 150,663
  • 30
  • 266
  • 294
4
var boolValue: Bool? = nil
var stringValue = "\(boolValue)" // can be either "true", "false", or "nil"

Or a more verbose custom function:

func boolToString(value: Bool?) -> String {
    if let value = value {
        return "\(value)"
    }
    else { 
        return "<None>"
        // or you may return nil here. The return type would have to be String? in that case.
    }

}

TotoroTotoro
  • 17,524
  • 4
  • 45
  • 76
0

You can do it with extensions!

extension Optional where Wrapped == Bool {
  func toString(_ nilString: String = "nil") -> String {
    self.map { String($0) } ?? nilString
  }
}

Usage:

let b1: Bool? = true
let b2: Bool? = false
let b3: Bool? = nil

b1.toString() // "true"
b2.toString() // "false"

b3.toString() // "nil"
b3.toString("<None>") // "<None>"
Fred
  • 381
  • 5
  • 17