Float conversion crash - swift

I have this :
let value = data[1] // its a string
print("val:",value) // prints 28.3
let a:Float = Float(value)!
print("a:",a)
Which prints a ok till sometimes crashes where value has a value on it
fatal error: unexpectedly found nil while unwrapping an Optional value
I can put the question mark to mark it as optional, but I am trying to understand how it crashes when there is a value .

Try to use optional wrapping with if let.
if let a = value as? Float {
print("a:%f",a)
}
To remove space try like this
let newValue = value.stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceCharacterSet())
Swift 3
let newValue = value.trimmingCharacters(in: .whitespaces)

Related

How to remove optional from a string value in swift?

In the code I'm not able to remove optional from the value inside the lbltotalamount.
The value in lblTotalAmount is not removing its optional value from it.
Why? The value in grandtotal gets optional removed but when I assign it to a label it returns an optional value again.
The lblTottalAmount is getting an optional value. I want to remove it.
if success == false {
var grandtotal: Any? = value["total"]
if grandtotal != nil {
print("O!O!O!O/\(grandtotal!)")
grandtotal = String(describing: grandtotal)
self.lblTotalAmount.text = ([grandtotal]) as! String // (here I am not able to remove optional)
}
The problem is in the line
grandtotal = String(describing: grandtotal)
You check for nil but you don't unwrap the value so it's still an optional.
And you are misusing String(describing. Never use it for types which can be converted to String with an init method.
Use always conditional downcast
if success == false {
if let grandtotal = value["total"] as? Double {
self.lblTotalAmount.text = String(grandtotal)
}
}

Why is it everytime I try to get a user to input an integer in Swift, Xcode makes me put a "!" after the variable

I'm working on a code where I need to get 2 user inputted integers and output the smaller one. I am new to swift, and every time I try to get a user to input an integer, I get this error "Value of optional type 'String?' must be unwrapped to a value of type 'String'". I don't understand why I always need to put a "!" after readLine(), but thats what it makes me do.
print("Enter the first integer")
let int1 = Int(readLine()!)
print("Enter the second integer")
let int2 = Int(readLine()!)
let small_int = min(int1!, int2!)
print("The smaller integer is", small_int)
As you can read in docs:
The string of characters read from standard input. If EOF has already been reached when readLine() is called, the result is nil.
... so, simplified, readLine(strippingNewline:) always doesn't have to return value and it also can return nil (no value), so return type is String? which is optional type which says that your constant is String or nil
If you need to get non-optional value you can either force-unwrap optional value or check if value exists and if does, assign some non-optional constant/variable using optional binding. The same you can do for Int initializer which can also return nil since not every String is necessarily a integer
print("Enter the first integer")
let input1 = readLine()
print("Enter the second integer")
let input2 = readLine()
if let string1 = input1, let int1 = Int(string1), let string2 = input2, let int2 = Int(string2) {
let small_int = min(int1, int2)
print("The smaller integer is", small_int)
} else {
print("Invalid input")
}
alternatively you can use default value so if value is nil your constant will be assigned with given default value
print("Enter the first integer")
let int1 = Int(readLine() ?? "") ?? 0
print("Enter the second integer")
let int2 = Int(readLine() ?? "") ?? 0
let small_int = min(int1, int2)
print("The smaller integer is", small_int)
I recommend writing your code in a defensive way. That includes dealing with unexpected results.
Both, readline() and Int() can return nil. As the other answer already explained, readline returns nil if you have reached EOF.
So my recommendation is to use the ?? operator to provide alternative values for the failure cases. For example: let line = readline() ?? “”.
Alternatively, especially inside methods, you may want to bail out early with guard and have the actual work at the end of the method with validated and non-nil inputs.
With that in mind, your example can be rewritten like this:
let line = readline() ?? “”
let int1 = Int(line) ?? 0
//...
Or as a method with guard:
func smallerInteger() -> Int? {
print("Enter the first integer")
guard let line1 = readline() else {
return nil
}
guard let int1 = Int(line1) else {
return nil
}
print("Enter the second integer")
guard let line2 = readline() else {
return nil
}
guard let int2 = Int(line2) else {
return nil
}
return min(int1, int2)
}
Of course this can be improved by returning both an Int? and an Error? like (Int?, Error?) or with the latest Swift, a Result.

Convert optional string to Int crashes in spite of having value

I check the optional string
print(limitCash)
if let value = Int32(limitCash) {
aProvider.limitBuy = value
}
The value of limitCash is Optional("500").
The program checks if let statement and skips it without assigning value.
Program crashes if I try aProvider.limitBuy = Int32(limitCash)!
First you need to unwrap String? to String and then unwrap the result of casting from String to UInt32 (that will be Uint32?).
print(limitCash)
if let stringValue = limitCash {
if let value = Int32(stringValue) {
print(value) // 500
}
}

Says type is non-optional but prints optional

I have this code:
let result_string = "\(String(describing: value))"
because I need to convert this from type Any to String. However when I print result string, it prints:
optional(abcd)
How do I make it print just
abcd
?
When I tried the other fixes for optionals it told me that result_string is not optional and didn't let me force unwrap.
EDIT:
Value was an optional, so force unwrapping it fixed my problem.
let result_string = "\(String(describing: value!))"
You can try
if let res = value {
print(res)
}
OR
guard let res = value { return }
print(res)
you can try like below:
var value : Any? = "abcd"
let result_string = value as! String
print(result_string)
We have to downcast Any to string.
Worked in playground.

Swift Optional Dictionary [String: String?] unwrapping error

So here I have a basic setup
var preferenceSpecification = [String : String?]()
preferenceSpecification["Key"] = "Some Key"
preferenceSpecification["Some Key"] = nil
preferenceSpecification["DefaultValue"] = "Some DefaultValue"
print(preferenceSpecification)
var defaultsToRegister = [String : String]()
if let key = preferenceSpecification["Key"], let defaultValueKey = preferenceSpecification["DefaultValue"] {
defaultsToRegister[key] = preferenceSpecification[defaultValueKey]!
}
But the error points out where it demands that I force unwrap this, to be like this:
defaultsToRegister[key!] = preferenceSpecification[defaultValueKey!]!
Which doesn't make sense, because keyValue and defaultValue already are unwrapped
When you extract a value from a dictionary like this using subscript
[String: String?]
you need to manage 2 levels of optional. The first one because the subscript returns an optional. The second one because the value of you dictionary is an optional String.
So when you write
if let value = preferenceSpecification["someKey"] {
}
you get value defined as an optional String.
Here's the code to fix that
if let
optionalKey = preferenceSpecification["Key"],
key = optionalKey,
optionalDefaultValueKey = preferenceSpecification["DefaultValue"],
defaultValueKey = optionalDefaultValueKey,
value = preferenceSpecification[defaultValueKey] {
defaultsToRegister[key] = value
}
Suggestions
You should avoid force unwrapping as much as possible. Instead you managed to put 3 ! on a single line!
You should also try to use better name for your constants and variables.
You could also define an extension which helps get rid of the double optional situation.
extension Dictionary where Value == Optional<String> {
func flattened(_ key: Key) -> Value {
if let value = self[key] {
return value
}
return nil
}
}
Usage: preferenceSpecification.flattened("someKey")