Function returning Optional("String") - swift

I have this function that accepts an Double value, convert it to a currency format and return a String formatted like R$:1.200,30.
func convert_Value(valor: Double) ->String {
let formatter = NSNumberFormatter()
formatter.numberStyle = NSNumberFormatterStyle.CurrencyStyle
formatter.locale = NSLocale(localeIdentifier: "pt_BR")
return ("\(formatter.stringFromNumber(valor))")
}
This function doesn't have any Optional variable declared, but when i call it using:
x = convert_Value(1200.30)
it returns:
Optional("R$1.200,30")
I can't figure out what i need to do, as its not an optional i can't use exclamation marks to unwrap the optional.
I tried to turn the Double and String parameter in function as Optional and then unwrap, but the Optional stills showing.

It doesn't return Optional("R$1.200,30"), it returns "Optional("R$1.200,30")". There's a subtle difference there; notice the ". What's happening is formatter.stringFromNumber(valor) returns String?, which you're putting in a String using "\(...)". Instead, you should return formatter.stringFromNumber(valor)!, force unwrapping here is okay because you know the input is a number.

Related

How to get an NSNumber from a String of decimal?

I'm not sure what I'm doing wrong, but NumberFormatter fails to get a number from a simple decimal String when using the number(from:) method.
Here's an example:
let decimalString: String = "12.5"
let formatter = NumberFormatter()
let number = formatter.number(from: decimalString)
print(number) // nil
Please keep in mind that I'm using NumberFormatter to handle decimals from any locale, so passing "١٢٫٥" should also lead to a non-nil return value from number(from:).
What is the correct and locale-aware way of converting any string from a UITextField that is entered using keyboard type .decimalPad to a valid NSNumber and get the doubleValue from it? (shortcuts like using the Double initializer or the .asciiCapableNumberPad keyboard type are not ideal)

Why is this still optional?

I make a query that returns a NSNumber. I then attempt to cast the NSNumber to String. For some reason, it always prints/ compares as an optional...but when I check the variables type it says string...Why is it optional? I need it to be a string!
let whoseTurn = selectedGame?["currentSender"]
let whoseTurnAsString: String = String(describing: whoseTurn)
if let whoseTurn = selectedGame?["currentSender"] as? NSNumber {
let whoseTurnAsString = "\(whoseTurn)"
print(whoseTurnAsString)
}
This is the right way to do optional chaining and make sure you are not forcing an optional
whoseTurn is an optional wrapping your NSNumber. You aren't "casting" it here to a string, you are making a string that "describes" it, and in this case that description includes the fact that whoseTurn is an optional... If you don't want that you'll need to unwrap it,
let whoseTurnAsString: String = String(describing: whoseTurn!)
(note the ! at the end)
This line of code let whoseTurn = selectedGame?["currentSender"] will return an optional.
This line of code let whoseTurnAsString: String = String(describing: whoseTurn) will return a String describing that optional value, which will be a string like this: Optional(5) or Optional(6). It describes the value saying that it is an optional.
So you need to unwrap that optional in order to get the wrapped value, you can force unwrap selectedGame like this:
let whoseTurn = selectedGame!["currentSender"] and then use the normal String initializer like this: String(whoseTurn).
Or, preferably, safely unwrap it like this:
if let whoseTurn = selectedGame?["currentSender"] {
let whoseTurnAsString = String(whoseTurn)
}
String can be optional also '?' or '!' indicates optional, check documentation on optionals.

Type cast optional values

Whenever we need to du something with an optional value in swift we need to unwrap it to operate, not on the optional, but on the value ”inside” the optional.
var optionalString:String? = "Hello"
optionalString!.append(" World!")
Note the exclamation mark on the second line.
But when using the optional type cast operator (as?) on an optional value, one does not need to unwrap the optional, we just provide it with the optional itself, and it just magically works.
let sneakyString:Any? = "Hello!"
let notSoSneakyString = sneakyString as? String
Note the absent exclamation mark on the second line.
The magic is a bit more obvious if we spell it out:
let sneakyString:Any? = Optional("Hello")
let notSoSneakyString = sneakyString as? String
Its not a string we're trying to cast but an enum with a string as an associated value.
I would expect that I would have to do this:
let sneakyString:Any? = "Hello!"
let notSoSneakyString = sneakyString! as? String
Note the exclamation mark on the second line.
Does the type cast operators act on optionals and non optionals in the same way?
The as? operator makes a cast if it possibly can, and returns either the casted object or nil. It handles nil values too, so that if sneakyString were nil, you wouldn't have been able to cast it to a String and the cast would have failed. Same behaviour as if it were non-nil but not castable to String.
In other words, you don't need the ! because as? handles nil values automatically itself.

Convert optional string to int in Swift

I am having troubles while converting optional string to int.
println("str_VAR = \(str_VAR)")
println(str_VAR.toInt())
Result is
str_VAR = Optional(100)
nil
And i want it to be
str_VAR = Optional(100)
100
At the time of writing, the other answers on this page used old Swift syntax. This is an update.
Convert Optional String to Int: String? -> Int
let optionalString: String? = "100"
if let string = optionalString, let myInt = Int(string) {
print("Int : \(myInt)")
}
This converts the string "100" into the integer 100 and prints the output. If optionalString were nil, hello, or 3.5, nothing would be printed.
Also consider using a guard statement.
You can unwrap it this way:
if let yourStr = str_VAR?.toInt() {
println("str_VAR = \(yourStr)") //"str_VAR = 100"
println(yourStr) //"100"
}
Refer THIS for more info.
When to use “if let”?
if let is a special structure in Swift that allows you to check if an Optional holds a value, and in case it does – do something with the unwrapped value. Let’s have a look:
if let yourStr = str_VAR?.toInt() {
println("str_VAR = \(yourStr)")
println(yourStr)
}else {
//show an alert for something else
}
The if let structure unwraps str_VAR?.toInt() (i.e. checks if there’s a value stored and takes that value) and stores its value in the yourStr constant. You can use yourStr inside the first branch of the if. Notice that inside the if you don’t need to use ? or ! anymore. It’s important to realise thatyourStr is actually of type Int that’s not an Optional type so you can use its value directly.
Try this:
if let i = str_VAR?.toInt() {
println("\(i)")
}

"if let" statement executed despite value being nil

I have an "if let" statement that is being executed, despite the "let" part being nil.
if let leftInc : Double? = self.analysis.inputs[self.btnLeftIncisor.dictionaryKey!]! {
println(leftInc)
let valueString : String = formatter.stringFromNumber(NSNumber(double: leftInc!))!
self.leftIncisorTextField?.text = valueString
self.btnLeftIncisor.associatedLabel?.text = valueString
}
// self.analysis.inputs is a Dictionary<String, Double?>
The inputs dictionary holds information entered by the user - either a number, or nil if they haven't entered anything in the matching field yet.
Under the previous version of Swift, the code was written as this:
if let leftInc : Double? = self.analysis.inputs[self.btnLeftIncisor.dictionaryKey!]?? {
and worked correctly.
I saw a similar question here, but in that instance the problem seemed to be the result of using Any?, which is not the case here.
Swift 2.2
In your if let you define another optional, that's why nil is a legitimate case. if let is intended mainly to extract (maybe) non optional value from an optional.
You might try:
if let leftInc : Double = self.analysis.inputs[self.btnLeftIncisor.dictionaryKey!].flatMap ({$0}) {
// leftInc is not an optional in this scope
...
}
Anyway I'd consider to not do it as a one liner but take advantage of guard case. Just in order to enhance readability. And avoid bang operator (!).
The if-let is for unwrapping optionals. You are allowing nil values by setting the type to an optional Double.
The if statement should be:
if let leftInc = self.analysis.inputs[self.btnLeftIncisor.dictionaryKey!] as? Double{
...
}
This will attempt to get an object out of inputs, if that fails it returns nil and skips it. If it does return something it will attempt to convert it to a Double. If that fails it skips the if statement as well.
if inputs is a dictionary like [Something:Double] then you don't need the last as? Double as indexing the dictionary will return a Double?
I recommend reading the swift book on optional chaining.
You could break it down further -
if let optionalDouble = self.analysis.inputs[self.btnLeftIncisor.dictionaryKey!], leftInc = optionalDouble {
....
}
as your dictionary has optional values - this way of writing it might make it clearer what's going on
if let k = dict["someKey"]{}, dict["someKey"] will be an object of type Any
this can bypass a nill
So do a typecast to get it correct like if let k = dict["someKey"] as! String {}