Bool Being Seen as Int When Using Anyobject

Bool being seen as int when using AnyObject

Instead of:

var params = Dictionary<String,AnyObject>()

Try:

var params = Dictionary<String,Any>()

Any can represent an instance of any type at all, including function
types.

Documentation:
https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/TypeCasting.html#//apple_ref/doc/uid/TP40014097-CH22-XID_448

In this case it appears you need a Dictionary and the service is expecting "true" as opposed to the bool value.

I recommend creating a function to convert your bool value to a String and using that to set your params["tester"].

Example:

param["tester"] = strFromBool(true)

and then define the function strFromBool to accept a bool parameter and return "true" or "false" depending on its value.

AnyObject bool is converted to int

Update:

The problem actually lies in the type of paramOptions. Bool technically does not conform to AnyObject, and as such, Bool values are converted into numbers to be stored as an AnyObject. Normally, this is not an issue, as they can be freely converted back into Bools.

I don't know the broader scope of this code (or where it has to interoperate with Objective C), but changing your declarations to the following would resolve the issue:

var parameters : Dictionary<String, Any> = Dictionary()
var paramOptions: Dictionary<String, Any> = Dictionary()
var arrayOptions = [Dictionary<String, Any>]()

The issue here is that Bool is not an AnyObject, so the Bool value is being bridged to an NSNumber automatically. Bool is an Any, however, and is left unchanged with the updated types.

Why does in Swift3 boolean value from NSUserDefaults is visible as 0 instead of false ?

Whenever you convert a Bool to AnyObject, true becomes 1 and false becomes 0. That behaviour cannot be changed I don't think.

// prints 1
print(true as AnyObject)

The only workaround that I can think of is:

var params = [
"switch1": defaults.bool(forKey: "mySwitch").description as AnyObject
] as [String: AnyObject]
print(params)

As you can see, I accessed description before as AnyObject. The output is shown below:

["switch1": false]

Apparently, "switch1" gets those quote marks but not false.

Note that I know nothing about Alamofire so I don't know whether sending ["switch1": false] as a parameter to a server will work.

Is it possible to distinguish Bool and Int in Swift?

func checkType<T>(value: T) -> String {
var statusText = "not found"
if value is Int {
statusText = "It is an integer"
} else if value is Bool {
statusText = "It is an boolean"
} else if value is String {
statusText = "It is an string"
}
return statusText
}

AnyObject cannot be implicitly downcast to any type in Swift. For such case you can use Generics instead.

Generic code enables you to write flexible, reusable functions and types that can work with any type, subject to requirements that you define. Read more.

How can this AnyObject? has boolValue property

Command-click on AnyObject and you will find the answer:

/// The protocol to which all classes implicitly conform.
///
/// When used as a concrete type, all known `@objc` methods and
/// properties are available, as implicitly-unwrapped-optional methods
/// and properties respectively, on each instance of `AnyObject`. For
/// example:
///
/// class C {
/// @objc func getCValue() -> Int { return 42 }
/// }
///
/// // If x has a method @objc getValue()->Int, call it and
/// // return the result. Otherwise, return nil.
/// func getCValue1(x: AnyObject) -> Int? {
/// if let f: ()->Int = x.getCValue { // <===
/// return f()
/// }
/// return nil
/// }
///
/// // A more idiomatic implementation using "optional chaining"
/// func getCValue2(x: AnyObject) -> Int? {
/// return x.getCValue?() // <===
/// }
///
/// // An implementation that assumes the required method is present
/// func getCValue3(x: AnyObject) -> Int { // <===
/// return x.getCValue() // x.getCValue is implicitly unwrapped. // <===
/// }
///
/// - SeeAlso: `AnyClass`
@objc public protocol AnyObject {
}

So, you can call any @objc method on an AnyObject instance.

If you type

let a: AnyObject?

in a Playground and then:

a?.

autocomplete will show you the complete list of methods you can call. And it is huge.

Converting Int to Bool

No, there is and has never been an explicit built in option for conversion of Int to Bool, see the language reference for Bool for details.

There exists, still, however, an initializer by NSNumber. The difference is that implicit bridging between Swift numeric type and NSNumber has been removed in Swift 3 (which previously allowed what seemed to be explicit Bool by Int initialization). You could still access this by NSNumber initializer by explicitly performing the conversion from Int to NSNumber:

let number = 1
let result = Bool(number as NSNumber)

print(result) // true

As @Hamish writes in his comment below: if we leave the subject of initializers and just focus on the end result (instantiating a Bool instance given the value of an Int instance) we can simply make use of the != operator for Int values (specifically, the operator with signature func !=(lhs: Int, rhs: Int) -> Bool), a generalization easily achievable using the != operator approach:

let number = -1
let result = number != 0

print(result) // true

Much like you yourself as well as @JAL describes in his answer, you could construct your own Bool by Int initializer, but you might as well consider generalizing this for any type conforming to the Integer protocol:

extension Bool {
init<T: Integer>(_ num: T) {
self.init(num != 0)
}
}

/* example usage */
let num1: Int8 = -1
let num2: Int = 3
let num3: UInt64 = 0
// ....
let result1 = Bool(num1) // true
let result2 = Bool(num2) // true
let result3 = Bool(num3) // false

Determine that `true` is a Bool and not a number equal to 1

1, 1.0, true, all types are bridged to NSNumber

You can check the objCType

let some : AnyObject = true

if let type = String.fromCString(some.objCType) {
switch type {
case "c" : print("is Bool", some as! Bool)
case "q" : print("is Int", some as! Int)
case "d" : print("is Double", some as! Double)
default : print("no idea")
}
} else {
print("no matching objCType")
}

Source: Type Encodings

Convert Unmanaged AnyObject ! to Bool in Swift

It's been a long time since this has remained unanswered so I'm adding what I have learned along the way.

To convert a BOOL value returned by an Objective C method you can simply cast it using,

if let result = controlDelegate.performSelector("methodThatReturnsBOOL") {
print("true")
} else {
print("false")
}

Here you can also assign the value true/false to a Swift Bool, if required.

Note : I tried casting Unmanaged<AnyObject> directly to Bool using takeRetainedValue() as suggested by many answers on SO, but that doesn't seem to work in this scenario.

((Any) throws - Bool) throws - Optional Any ') cannot conform to 'BinaryInteger'

With help from @Rob in the comments, I was able to unwrap the message properly and remove unnecessary guard let statements to run my delegate function. Below is the updated piece of code.

  1. Changed message.values.first? as Int as the rate was in an integer format.
  2. Removed guard let statements in converting the heartRate into the double format, as it was non-optional.
extension WatchKitConnection: WCSessionDelegate {

func session(_ session: WCSession, didReceiveMessage message: [String : Any]) {
print("didReceiveMessage from watch")
print(message)

// delegate?.updateLatestHeartRate(Double(message.values.first))

guard let heartRate = message.values.first as? Int else {
return
}

let heartRateDouble = Double(heartRate)

print("printing heartRate double from message\(heartRateDouble)")

delegate?.updateLatestHeartRate(heartRateDouble)

print("updateLatestHeartRate")

}
}


Related Topics



Leave a reply



Submit