1

I have this variable here, its an Any

 item["completed"]

Its either 1 or 0 which is true or false from mysql database, how can I covert the 1 or 0 to true or false?

I have tried this:

 (item["completed"] as! NSNumber).boolValue)

but I get this error

Could not cast value of type 'NSTaggedPointerString' (0x10f906560) to 'NSNumber' (0x10e455d40).

user979331
  • 11,039
  • 73
  • 223
  • 418

3 Answers3

1

You can try below extension which i have implemented,

extension String {

    var bool: Bool {
        return self == "1" ? true : false
    }
}

 (item["completed"] as? String).bool

Hope this way may help you.

Ahemadabbas Vagh
  • 492
  • 3
  • 15
0

Just use

let isCompleted = "1" == (item["completed"] as? String)

If you are using Decodable for json parsing, you can use following ApiBool struct instead of Bool

struct ApiBool: Codable {
    let value: Bool

    init(from decoder: Decoder) throws {
        let container = try decoder.singleValueContainer()

        if let string = try? container.decode(String.self) {
            self.value = string == "1"
        } else {
            let intVal = try container.decode(Int.self)
            self.value = intVal == 1
        }
    }

    func encode(to encoder: Encoder) throws {
        var container = encoder.singleValueContainer()
        try container.encode(self.value ? 1 : 0)
    }
}

Note As mentioned in comments, you got an String data type and it is expected to be an integer, this is caused by libmysql driver, you can connect to MySQL using mysqlnd driver instead, this will result in a JSON with proper numeric data types, following posts might help you configure the driver

https://stackoverflow.com/a/46690317/1244597

https://stackoverflow.com/a/45366230/1244597

AamirR
  • 11,672
  • 4
  • 59
  • 73
0

@ahemadabbas-vagh shared a good and reusable approach. But if we talk about computer science, a string's Boolean equality should not be measured like that.

This approach is the same as his, but it asks Bool if the value is true or false, not to String. Bool should know is a value is true or false, not String.

var str = "1"

extension Bool {
  static func from(stringValue str: String) -> Bool {
    return str == "1"
  }
}

if Bool.from(stringValue: str) {
  print("TRUE")
} else {
  print("FALSE")
}

But it is still not correct. In computer science, null/nil or/and an empty string should be false and any other strings should be true. You can add the string "0" to this set.

You can implement like this; better approaches still might exist. The idea is; globally a string can only be converted to true if it is not "0", not "" (empty string), not null/nil or if it is "true".

var str = "1" // check for nil, empty string and zero; these should be false; any other string should be true.

extension Bool {

  static func from(stringValue str: String) -> Bool {

    if str == "true" {
      return true
    }

    guard let intVal = Int(str) else {
      return false
    }
    return Bool(truncating: intVal as NSNumber)
  }
}

if Bool.from(stringValue: str) {
  print("TRUE")
} else {
  print("FALSE")
}

If you use Decodable protocol; I know you know how to handle but:

struct aStruct: Decodable {

  let boolVal: Bool

  enum CodingKeys: String, CodingKey {
    case completed
  }

  init(from decoder: Decoder) throws {
    let container = try decoder.container(keyedBy: CodingKeys.self)
    let boolString = try container.decode(String.self, forKey: .completed)
    self.boolVal = Bool.from(stringValue: boolString)
  }

}
Arda Oğul Üçpınar
  • 881
  • 1
  • 14
  • 38
  • 1
    Basically your suggestion is correct but mysql returns reliably either `"0"` or `"1"` as Bool value, nothing else. – vadian May 11 '19 at 18:55
  • Yes, these already and also covers that. Check on a playground. Any code you have implement need to be reusable and fit to computer science as much as possible. I'm trying to give you something suits this idea. – Arda Oğul Üçpınar May 11 '19 at 18:59