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.
- Changed
message.values.first?
asInt
as the rate was in an integer format. - 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
Spacer Not Working with Form Inside a VStack
How to Remove Optional from String Value Swift
Convert a Custom Object to Data to Be Saved in Nsuserdefauts
Uicollectionviewlayout Not Working with Uiimage in Swift 5 and Xcode 11
Why Can't the Swift Compiler Infer This Closure's Type
Why Can't I Use a Tuple Constant as a Case in a Switch Statement
Converting a C-Style for Loop That Uses Division for the Step to Swift 3
Know When an Iteration Over Array with Async Method Is Finished
Is This a Good Way to Display Asynchronous Data
How to Write a Function That Will Unwrap a Generic Property in Swift Assuming It Is an Optional Type
Parameters After Opening Bracket
Xcode Beta 6 "Type of Expression Is Ambiguous Without More Context" Navigationlink
Why Can't We Use Protocol 'Encodable' as a Type in the Func
How to Disable Vertical Scroll in Tabview with Swiftui