orkenstein
orkenstein

Reputation: 2858

How to check dictionary value to be exactly a Bool?

Let's say we have something like this:

  static func convertBoolToString(source: [String: AnyObject]) -> [String:AnyObject]? {
    var destination = [String:AnyObject]()
    for (key, value) in source {
      switch value {
      case is Bool:
        destination[key] = "\(value as! Bool)"
      default:
        destination[key] = value
      }
    }

    if destination.isEmpty {
      return nil
    }
    return destination
  }

The problem is that if value is Double or Int or anything convertible to Bool it will pass the first case.
Pls, check the doc: https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/TypeCasting.html

How to check the value to be exactly and only a Bool?

Upvotes: 1

Views: 2623

Answers (2)

bubuxu
bubuxu

Reputation: 2197

Swift 3 version:

static func convertBoolToString(_ source: [String: Any]?) -> [String:Any]? {
    guard let source = source else {
        return nil
    }
    var destination = [String:Any]()
    let theTrue = NSNumber(value: true)
    let theFalse = NSNumber(value: false)
    for (key, value) in source {
        switch value {
        case let x as NSNumber where x === theTrue || x === theFalse:
            destination[key] = "\(x.boolValue)"
        default:
            destination[key] = value
        }
    }
    return destination
}

Upvotes: 2

Sulthan
Sulthan

Reputation: 130102

This is a tricky problem. Note that neither Bool, Double or Int are AnyObject, they are all value types. That means they are represented in the dictionary as NSNumber. However, NSNumber can convert any value it holds to a Bool.

Checking which type is inside NSNumber is not easy. One way to check is to compare references with the result of NSNumber(bool:) constructors because NSNumber returns always the same instance:

func convertBoolToString(source: [String: AnyObject]) -> [String:AnyObject]? {
    var destination = [String:AnyObject]()

    let theTrue = NSNumber(bool: true)
    let theFalse = NSNumber(bool: false)

    for (key, value) in source {
        switch value {
        case let x where x === theTrue || x === theFalse:
            destination[key] = "\(value as! Bool)"
        default:
            destination[key] = "not a bool"
        }
    }

    if destination.isEmpty {
        return nil
    }
    return destination
}

let dictionary: [String: AnyObject] = ["testA": true, "testB": 0, "testC": NSNumber(bool: true)]
print("Converted: \(convertBoolToString(dictionary))")

For other options, see get type of NSNumber

Upvotes: 2

Related Questions