How to cast an Any object to a Double. I was able to cast it to a string but I can't find anywhere to cast to a Double. Either read in zip code as a Double or cast zip code after to a Double.
let zipCode = ((o as AnyObject).fieldValue("Zip__c"))!
//String cast that works
lender.First_Name__c = String(describing: zipCode)
The short answer is that you can use as to cast, though you can do this in a few ways. The safe, Swift way of doing it is with optional binding, like this:
if let doubleValue = o as? Double {
print(doubleValue)
}
If you can guarantee it's a Double you can force unwrap it like so:
let doubleValue = o as! Double
Related
So is there another way of conversion without it being explicit?
Lets say, this is the string
var stringValue = "123"
You can convert it into "INT" two ways
first is
let intNumber : Int = Int(stringValue)!
second is
let anotherIntNumber : Int = (stringValue as NSString).integerValue // go with first 1 as this is more of objective-c
If you confirm String to ExpressibleByIntegerLiteral you can just write this:
let myVar: String = 1
print(myVar)
Just note that you need to explicitly provide a type for myVar as compiler doesnt know which type it shouldd choose from.
How do we conform String to ExpressibleByIntegerLiteral? Something like this:
extension String : ExpressibleByIntegerLiteral {
public init(integerLiteral value: Int) {
self = String(value)
}
}
for the other way round you can look at ExpressibleByStringLiteral
I'd like to implement automatic type conversions between known types in Swift. The C# way of doing it has been overloading type-casting operators. If I want my X type to be cross-assignable with, say, string, I would write:
public class X
{
public static implicit operator string(X value)
{
return value.ToString();
}
public static implicit operator X(string value)
{
return new X(value);
}
}
After that I could write stuff like:
string s = new X();
X myObj = s;
and they would be automatically converted. Is that possible in any way in Swift?
No, the language doesn't provide such functionality for custom types. There is bridging between Objective-C collections and Swift collections but that's baked in and not customizable.
// Swift array of `String` elements
let swiftArray: [String] = ["Bob", "John"]
// Obj-C array of `NSString` elements, but element type information
// is not known to the compiler, so it behaves like an opaque NSArray
let nsArray: NSArray = ["Kate", "Betty"]
// Obj-C array of an `NSString` and an `NSNumber`, element type
// information is not known to the compiler
let heterogeneousNSArray: NSArray = ["World", 3]
// Casting with `as` is enough since we're going from Swift array to NSArray
let castedNSArray: NSArray = swiftArray as NSArray
// Force casting with `as!` is required as element type information
// of Obj-C array can not be known at compile time
let castedSwiftArray: [String] = nsArray as! [String]
// Obj-C arrays can not contain primitive data types and can only
// contain objects, so we can cast with `as` without requiring a
// force-cast with `!` if we want to cast to [AnyObject]
let heterogeneousCastedNSArray: [AnyObject] = heterogeneousNSArray as [AnyObject]
Documentation for type casting is available here.
I think you can achieve what you want to do with initializers.
extension X {
init(string: String) {
self = X(string)
}
}
extension String {
init(x: X) {
// toString is implemented elsewhere
self = x.toString
}
}
let x = X()
let string = "Bobby"
let xFromString: X = X(string: string)
let stringFromX: String = String(x: x)
Not directly related to your question but there is also a family of protocols that start with ExpressibleBy..., enabling you to do things like the following:
Let's say we want to initialize strings from integer literals. We can do that by conforming to and implementing ExpressibleByIntegerLiteral
// Strings can not be initialized directly from integer literals
let s1: String = 3 // Error: Can not convert value of type 'Int' to specified type 'String'
// Conform to `ExpressibleByIntegerLiteral` and implement it
extension String: ExpressibleByIntegerLiteral {
public init(integerLiteral value: Int) {
// String has an initializer that takes an Int, we can use that to
// create a string
self = String(value)
}
}
// No error, s2 is the string "4"
let s2: String = 4
A nice use case for ExpressibleByStringLiteral can be found here.
I'm trying to understand why casting in the first case works while in the second it fails. What is the difference between the two?
var myVariable = 2
var myDoubleTest1 = Double(myVariable)
var myDoubleTest2 = myVariable as? Double
print(myDoubleTest1) // 2.0
print(myDoubleTest2) // nil
var myDoubleTest1 = Double(myVariable)
This line is just an initializer on Double. It takes an int, and initializes a new double. The documentation is here.
var myDoubleTest2 = myVariable as? Double
The as? keyword in Swift performs a cast. This means, in English, "create a variable named myDoubleTest2. If myVariable is of type Double, then use that. Otherwise, make it nil. We know, from the first line in your code (var myVariable = 2), that myVariable is not a Double (it is an Int), so myDoubleTest2 will be nil. You can read more about type casting here.
The first case
var myDoubleTest1 = Double(myVariable)
you actually converts the Int to Double
but in second
var myDoubleTest2 = myVariable as? Double
it checks whether myVariable is of Double type & has no nil value if passed ,it assigns it's value to myDoubleTest2
I have a simple question, I have this dictionary:
let dict: [String: Any] = ["Area": "100", "YessorNo" : true]
And, for the key area, I want to cast it's value to a double, like so:
let a = dict["Area"] as? Double
When I print a, I get a nil, why? the value 100 is although a string but it is a number isn't? why can't I cast it to a double?
You can't directly cast a String to a Double, you need to use the proper initializer.
guard let numStr = dict["Area"] as? String else {
return
}
let a = Double(numStr)
First, cast from Any to String, and then use an initializer to convert it to Double.
if let a = dict["Area"] as? String, let aDouble = Double(a) {
print(aDouble)
}
Since the other answers provided the code, I will focus on the why of the question. Type casting won't work because, according to the Swift docs, type casting allows you to "treat that instance as a different superclass or subclass from somewhere else in its own class hierarchy." Since a double is not a subclass or a superclass of a string, you can't cast a string to a double even if that string is a string of a number. This is why trying to cast a string to a double returns nil.
I am quite new to Swift and when I learning about initializing a string, I find a wired syntax that I cannot understand.
For example
If I initialize a string using:
var str:String = "Hello, playground"
str.isEmpty
This works well
However, if I initialize a string with a constructor
var str = String("Hello, playground")
str.isEmpty
this does not work.
And the compiler fix it by changing the syntax to
str?.isEmpty
I have no idea about what is that “?” for.
Any suggestion is appreciated.
When you say:
let str = String("Hello, playground")
you're using String's init?(_ description: String) initialiser, which satisfies LosslessStringConvertible's initialiser requirement, as not all types that conform have a representation for an arbitrary string (for example, Double).
Because the initialiser is failable, it returns an optional string instance (i.e String?), hence why the compiler is prompting you to use optional chaining (if not already, I would highly recommend reading the optionals section of the language guide).
However it's worth noting there's absolutely no need for String's implementation of this initialiser to be failable – as a string can always represent a string! This will be fixed in Swift 4, it will be implemented as a non-failable initialiser satisfying the failable requirement. This is because it doesn't break the contract with the protocol of either returning a new instance or nil (it just never happens to do the latter).
In the mean time however, you could just force unwrap the result, as it will always succeed. But really the use of the initialiser here is completely redundant. You should use a string literal, such as in your first example:
let str = "Hello, playground"
str will simply be initialised to a non-optional String instance with the contents of the string literal. Note that Swift can infer str to be of type String – you don't need to explicitly annotate it as such.
var str = String("Hello, playground")
This produces what is called an "Optional". In Swift, if something can be null/nil, then it is wrapped in an Optional. The '?' tries to unwrap the optional and produce a String.
If you KNOW that the value can never be null, then you can force unwrap it like this:
var str = String("Hello, playground")
str!.isEmpty
or
var str2 = String("Hello, playground")!
str2.isEmpty
Generally though forced unwrapping is frowned upon, as it can lead to crashes. Better approaches:
struct MyError:Error {
var message:String
}
guard let str3 = String("Hello, playground") else {
throw MyError(message:"failed")
}
str3.isEmpty
if let str4 = String("Hello, playground") {
str4.isEmpty
}