I can't figure out why this 'optional' isn't working in scenario 1, but without the optional ? it works in scenario 2.
Using Swift v 1.2, xCode 6.2
var stuff = "6t"
// SCENARIO 1
// Why is this failing when stuff contains non-digit characters?
// i.e. it works if stuff = "45".
if let value: Int? = stuff.toInt() {
println("value \(value!)")
}
// SCENARIO 2
// This works!
if let value = stuff.toInt() {
println("val3 \(value)")
}
For Reference also see these SO Answers:
* I wonder if the Sift 1.2 example/Answer here is just plain wrong?
Swift - Converting String to Int
Converting String to Int in Swift
The first IF is always true.
Infact in both cases:
when the toInt() returns a valid Int
when returns nil
the if let will succeed (and yes, the first IF is useless).
Specifically in your code toInt() returns nil in both scenarios.
But in your first scenario you are simply accepting nil as a valid value to enter the THEN block.
There is no point of using if let value: Int?. If the if let works, then the value is an Int. There is no way that it could be nil. Therefore, you do not need to declare it as an optional.
Related
just a short question. In Swift it is possible to solve the following code:
var a: String;
a = "\(3*3)";
The arithmetic operation in the string will be solved. But i can´t figure out, why this following variation doesn´t work.
var a: String;
var b: String;
b = "3*3";
a = "\(b)";
In this case the arithmetic operation in var a will not be resolved. Any ideas why and how i can this get to work. Some things would be much more easier if this would work. Thanks for your answers.
In the second case, you are interpolating a string, not an arithmetic expression. In your example, it's a string you chose at compile time, but in general it might be a string from the user, or loaded from a file or over the web. In other words, at runtime b could contain some arbitrary string. The compiler isn't available at runtime to parse an arbitrary string as arithmetic.
If you want to evaluate an arbitrary string as an arithmetic formula at runtime, you can use NSExpression. Here's a very simple example:
let expn = NSExpression(format:"3+3")
println(expn.expressionValueWithObject(nil, context: nil))
// output: 6
You can also use a third-party library like DDMathParser.
Swift 4.2
let expn = "3+3"
print(expn.expressionValue(with: nil, context: nil))
But I also have a solution thats not the most effective way but could be used in some cases if your sure it's only "y+x" and not longer string.
var yNumber: Int!
var xNumber: Int!
let expn: String? = "3+3"
// Here we take to first value in the expn String.
if let firstNumber = expo?.prefix(1), let myInt = Int(firstNumber){
// This will print (Int : 3)
print("Int : \(myInt)")
// I set the value to yNumber
yNumber = myInt
}
// Here we take the last value in the expn string
if let lastNumber = optionalString?.suffix(1), let myInt = Int(lastNumber){
// This will print (Int : 3)
print("Int : \(myInt)")
// I set the value to xNumber
xNumber = myInt
}
// Now you can take the two numbers and add
print(yNumber + xNumber)
// will print (6)
I can't recommend this but it works in some cases
This won't be solved because this is not an arithmetic operation, this is a string:
"3*3"
the same as this
"String"
Everything you put in " it's a string.
The second example lets you construct a new String value from a mix of constants, variables, literals, and expressions:
"\(3*3)"
this is possible because of string interpolation \()
You inserted a string expression which swing convert and create expected result.
You can try to use evaluatePostfixNotationString method from that class.
The whole project is about recognizing math expression from camera image and calculating it after.
With optional chaining, if I have a Swift variable
var s: String?
s might contain nil, or a String wrapped in an Optional. So, I tried this to get its length:
let count = s?.characters?.count ?? 0
However, the compiler wants this:
let count = s?.characters.count ?? 0
My understanding of optional chaining is that, once you start using ?. in a dotted expression, the rest of the properties are made optional and are typically accessed by ?., not ..
So, I dug a little further and tried this in the playground:
var s: String? = "Foo"
print(s?.characters)
// Output: Optional(Swift.String.CharacterView(_core: Swift._StringCore(_baseAddress: 0x00000001145e893f, _countAndFlags: 3, _owner: nil)))
The result indicates that s?.characters is indeed an Optional instance, indicating that s?.characters.count should be illegal.
Can someone help me understand this state of affairs?
When you say:
My understanding of optional chaining is that, once you start using ?. in a dotted expression, the rest of the properties are made optional and are typically accessed by ?., not ..
I would say that you are almost there.
It’s not that all the properties are made optional, it’s that the original call is optional, so it looks like the other properties are optional.
characters is not an optional property, and neither is count, but the value that you are calling it on is optional. If there is a value, then the characters and count properties will return a value; otherwise, nil is returned. It is because of this that the result of s?.characters.count returns an Int?.
If either of the properties were optional, then you would need to add ? to it, but, in your case, they aren’t. So you don’t.
Edited following comment
From the comment:
I still find it strange that both s?.characters.count and (s?.characters)?.count compile, but (s?.characters).count doesn't. Why is there a difference between the first and the last expression?
I’ll try and answer it here, where there is more room than in the comment field:
s?.characters.count
If s is nil, the whole expression returns nil, otherwise an Int. So the return type is Int?.
(s?.characters).count // Won’t compile
Breaking this down: if s is nil, then (s?.characters) is nil, so we can’t call count on it.
In order to call the count property on (s?.characters), the expression needs to be optionally unwrapped, i.e. written as:
(s?.characters)?.count
Edited to add further
The best I can get to explaining this is with this bit of playground code:
let s: String? = "hello"
s?.characters.count
(s?.characters)?.count
(s)?.characters.count
((s)?.characters)?.count
// s?.characters.count
func method1(s: String?) -> Int? {
guard let s = s else { return nil }
return s.characters.count
}
// (s?.characters).count
func method2(s: String?) -> Int? {
guard let c = s?.characters else { return nil }
return c.count
}
method1(s)
method2(s)
On the Swift-users mailing list, Ingo Maier was kind enough to point me to the section on optional chaining expressions in the Swift language spec, which states:
If a postfix expression that contains an optional-chaining expression is nested inside other postfix expressions, only the outermost expression returns an optional type.
It continues with the example:
var c: SomeClass?
var result: Bool? = c?.property.performAction()
This explains why the compiler wants s?.characters.count in my example above, and I consider that it answers the original question. However, as #Martin R observed in a comment, there is still a mystery as to why these two expressions are treated differently by the compiler:
s?.characters.count
(s?.characters).count
If I am reading the spec properly, the subexpression
(s?.characters)
is "nested inside" the overall postfix expression
(s?.characters).count
and thus should be treated the same as the non-parenthesized version. But that's a separate issue.
Thanks to all for the contributions!
Converting a String to Int returns an optional value but converting a Double to Int does not return an optional value. Why is that? I wanted to check if a double value is bigger than maximum Int value, but because converting function does not return an optional value, I am not be able to check by using optional binding.
var stringNumber: String = "555"
var intValue = Int(stringNumber) // returns optional(555)
var doubleNumber: Double = 555
var fromDoubleToInt = Int(doubleNumber) // returns 555
So if I try to convert a double number bigger than maximum Integer, it crashes instead of returning nil.
var doubleNumber: Double = 55555555555555555555
var fromDoubleToInt = Int(doubleNumber) // Crashes here
I know that there's another way to check if a double number is bigger than maximum Integer value, but I'm curious as why it's happening this way.
If we consider that for most doubles, a conversion to Int simply means dropping the decimal part:
let pieInt = Int(3.14159) // 3
Then the only case in which the Int(Double) constructor returns nil is in the case of an overflow.
With strings, converting to Int returns an optional, because generally, strings, such as "Hello world!" cannot be represented as an Int in a way that universally makes sense. So we return nil in the case that the string cannot be represented as an integer. This includes, by the way, values that can be perfectly represented as doubles or floats:
Consider:
let iPi = Int("3.14159")
let dPi = Double("3.14159")
In this case, iPi is nil while dPi is 3.14159. Why? Because "3.14159" doesn't have a valid Int representation.
But meanwhile, when we use the Int constructor which takes a Double and returns non-optional, we get a value.
So, if that constructor is changed to return an optional, why would it return 3 for 3.14159 instead of nil? 3.14159 can't be represented as an integer.
But if you want a method that returns an optional Int, returning nil when the Double would overflow, you can just write that method.
extension Double {
func toInt() -> Int? {
let minInt = Double(Int.min)
let maxInt = Double(Int.max)
guard case minInt ... maxInt = self else {
return nil
}
return Int(self)
}
}
let a = 3.14159.toInt() // returns 3
let b = 555555555555555555555.5.toInt() // returns nil
Failable initializers and methods with Optional return types are designed for scenarios where you, the programmer, can't know whether a parameter value will cause failure, or where verifying that an operation will succeed is equivalent to performing the operation:
let intFromString = Int(someString)
let valueFromDict = dict[someKey]
Parsing an integer from a string requires checking the string for numeric/non-numeric characters, so the check is the same as the work. Likewise, checking a dictionary for the existence of a key is the same as looking up the value for the key.
By contrast, certain operations are things where you, the programmer, need to verify upfront that your parameters or preconditions meet expectations:
let foo = someArray[index]
let bar = UInt32(someUInt64)
let baz: UInt = someUInt - anotherUInt
You can — and in most cases should — test at runtime whether index < someArray.count and someUInt64 < UInt32.max and someUInt > anotherUInt. These assumptions are fundamental to working with those kinds of types. On the one hand, you really want to design around them from the start. On the other, you don't want every bit of math you do to be peppered with Optional unwrapping — that's why we have types whose axioms are stated upfront.
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)")
}
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 {}