This might be seen as a minor issue, but it just looks ugly in the code and I would like to solve it.
I have an optional variable declared and would like to change it later, if it is not empty (!= nil) The code for this is:
First declare
private var myVariable: Int? // Optional Integer variable
Later decrement, when not empty
{
if myVariable != nil {myVariable!--} // Same condition in "if" and in unwrapping
}
I need the ! even when it is assured with the if-condition that the variable has a value. This is redundant and means that Swift must do the same comparison twice.
Is there a more elegant way in doing this?
My current Xcode Version is 6.3.
Just as examples, you could do the following:
myVariable?++
myVariable?--
myVariable? += 10
This uses optional chaining - if myVariable has non-nil a value, it is unwrapped and incremented. Otherwise the statement returns nil.
Answer to your question is Optional Chaining.
myVariable?--
if let myVariable = myVariable { //if - let unwrapping
myVariable-- //don't need the suffix now
}
I belive the point of giving "!" after variable is so the Swift doesn't need to double check. You said with "!" that the myVariable is not nil and it has a value so it won't double check.
Related
I was just wondering what is the difference between "?" and "!" in swift, I'm new to swift. I tried looking for questions similar in here, but couldn't find any.
An optional type can be nil
var nameOfToy: String?
The toy may have a name;
nameOfToy = "Buzz"
so
print (nameOfToy!)
is Buzz.
The question mark indicates that it is optional, i.e. can be nil, so you have to UNWRAP it with the !. This is because the variable is optional.
But what happens if there is no name of a toy, and you use !. In this case you get a nasty crash.
These characters have different meanings depending on the context. More than likely you are referring to their uses in unwrapping optionals.
If you have a variable foo:
var foo: Int?
You have declared the variable as an Optional. An Optional is a variable that can contain some value, or no value (nil.) Think of an Optional as a box, or wrapper, around another data type. In order to get at the value inside the optional, you have to unwrap it.
The question mark is the unwrap operator.
Say you have a more complex object like a struct:
struct Foo {
bar: Int
}
var aFoo: Foo?
You've created an Optional instance of Foo called aFoo. The variable aFoo either contains a Foo object, or it contains nil.
You could use code like this:
if aFoo?.bar == 3 {
print("aFoo contains an int == 3")
} else {
print("aFoo is either nil or contains some other value")
}
The ! operator is the "force unwrap" operator. I call it the "crash if nil" operator. If you rewrite the code above using force-unwap:
if aFoo!.bar == 3 {
print("aFoo contains an int == 3")
}
Then there is no point in having an else clause, since if aFoo is nil, you are guaranteed to crash.
You should only use the force-unwrap operator if you are certain that the Optional is not nil.
Optionals are a very important concept in Swift, so you should study them, and the various ways to handle them, until it's second nature.
Make sure you learn about "optional chaining", "optional binding", the nil coalescing operator, guard statements, and force unwrapping, to name a few techniques to deal with optionals.
“To declare an optional, we just have to add a question mark after the type’s name.To read the value of an optional, we have to unwrap it by adding an exclamation mark at the end of the name.”
“Declaring implicitly unwrapped optionals”
“Swift provides the possibility to declare implicitly unwrapped optionals. These are optional variables declared with the exclamation mark instead of the question mark. The system reads these variables as optionals until they are assigned a value and therefore we don’t have to unwrap them anymore.”
var mynumber: Int!
mynumber = 5
var total = mynumber * 10 // 50
I am reading the following book, on Page #32 there is a code snippet. December 2014: First Edition.
Swift Development with CocoaJonathon Manning, Paris Buttfield-Addison,
and Tim Nugent
I know we can use ? to make a vairbale optional and ! to unwrap a optional vairbale in Swift
var str: String? = "string"
if let theStr = str? {
println("\(theStr)")
} else {
println("nil")
}
Why do we need ? in this line if let theStr = str? It seems working just fine with out it and making no difference.
You don't need it, and shouldn't have it. The optional binding evaluates the optional. If it's nil, it stops. If it's not nil, it assigns the value to your required variable and then executes the code inside the braces of the if statement.
EDIT:
The language has changed slightly since it was first given out in beta form. My guess is that the ? used to be required.
Some of the sample projects I've used from Github fail to compile and I've had to edit them to get them to work. this might be an example where the syntax has changed slightly.
The current version of Swift does not require it, as it is redundant since your variable is already an optional.
Whatever you put in the if let statement does have to be an optional though or you will receive an error
Bound Value in a conditional binding must be of Optional type
Furthermore, if you are casting to a type, you do need to use as? to cast to an optional type.
var str2: Any = ["some", "example"]
if let theStr = str2 as? [String] {
println("\(theStr)")
} else {
println("nil")
}
I didn't find any much difference while using ? and ! in Swift. Here is the some example code of when I use ?
var myString:String? = "Ganesh";
if myString{
println(myString)
}else{
println(myString)
}
OutPut was: Optional Ganesh
var myString:String? = "Ganesh";
myString = nil
if myString{
println(myString)
}else{
println(myString)
}
OutPut was: nil
and when I use !
var myString:String! = "Ganesh";
if myString{
println(myString)
}else{
println(myString)
}
OutPut was: Ganesh
var myString:String! = "Ganesh";
myString = nil
if myString{
println(myString)
}else{
println(myString)
}
OutPut was: nil
Can someone please help me to get brief on it? Thanks in advance
First, the technical difference:
When you use var y : String?, you have to use if let x = y { /* do something with x */ } or y! to be able to use the value inside y. y.toInt() will not work, because toInt() does not exist on Optional<String>.
When you use var y : String!, you are using an implicitly unwrapped optional. When you do y.toInt(), it will behave as if you had said y!.toInt(). This is the entire difference.
Now, usage:
If at all possible, use variables, return values or properties that aren't optionals at all.
If you must have optionals, if possible, use ? (ordinary optionals). This clearly signals that the optional may not have a value and that it is as a consequence of the design.
When the implicitly unwrapped optional - ! - is used, it shows that it is "probably" supposed to have a value, and it is usually used when the information about whether it should be optional or not simply is not available, like Objective-C frameworks. This makes working with values that nearly always have a value easier (because you don't have to type ! all the time), but it also means that they encourage code that don't check for nil and that may therefore crash and burn.
Apple uses the implicitly unwrapped optional when importing Cocoa frameworks, but they are also cleaning up a lot of their own frameworks to use ordinary ? optionals or non-optionals instead of implicitly unwrapped optionals, since that provides a lot more information about what to expect.
(Update 2014-09-30: I had completely mixed up the advice for "!" and "?" - "?" is meant to be preferred over "!". I have edited the answer.)
I know that an optional constant or variable with a question mark needs an exclamation mark to access its value. then, I tried to exam it with the following code.
var aaa:String? = "3"
println("aaa = \(aaa!)")
Yes. It was okay. It printed "3" on Console Output. and next exam I tried like that
var aaa:String? = "3"
println("aaa = \(aaa)")
It also printed "3" without any error message. It worked well.
I learned about Forced Unwrapping that en exclamation mark is needed to access to a value of Optional. But, I could access it without the mark. Is it right? I wonder what is wrong. Am I misunderstanding Optional?
You are correctly understanding Optionals and Forced Unwrapping. The reason that you can print the optional variable is that the type Optional can also be printed. If you print an Optional instead of the real value, it will either print the value if it has one, or "nil" if it doesn't.
Also, just in case you don't realize it. Forced Unwrapping will cause the whole program to crash if the optional is nil at the time. To be safer, you should use Optional Binding:
var aaa: String? = "3"
if let actualString = aaa {
// actualString becomes a non-optional version of aaa
// if aaa were nil, this block would not be run at all
println(actualString)
}
Also, some extra information about the printing of instances. Printing uses the protocol Printable which defines a description property. Anything that implements this protocol can customize the way they print out. Optional has its own implementation of this protocol which is how it decides to either print "nil" or the description of the actual value.
Println() will print the value if it has any otherwise it will print nil. Just to understand things better just try to assign value of aaa to another string variable. It will throw error that value of optional type not unwrapped.
var aString:NSString? = "Hello"
var bString = aString // Compiler allows, as you are assigning to optional type again.
var cString:NSString = aString // Compiler throws error. You cannot assign optional type without unwrapping.
So to answer your question you need to use ! to get the value.
Edit:
var foo:Bool?
foo = false
if foo { // This always evaluates to `True`
...
}
if foo! { // This condition will now fail
...
}
The reason foo evaluated to True is because it was not unwrapped. Since its not unwrapped its just checking whether it has a value or not(true or false does not matter).
When foo was unwrapped it returned a value False hence the second if condition failed.
The println function is a special case. It automatically unwraps the variable for you. If the variable were nil, it would print nil. In other contexts, you do need to unwrap the variable yourself.
I'm going through the swift docs, and in the optional segment, it talks about using the question mark -- ? -- to signify variables that might be nil. This can be used in an if statement to check for nil, but in the docs they assign the optional to a new variable in the conditional. Is there a reason for this?
For Example, it is presented in the docs similar to this:
// Declare an optional string (might be nil)
var optionalString: String? = "Hello"
// Assigns optionalString to new variable before checking if nil
if let string = optionalString {
println("\(optionalString) is not nil!")
}
else {
println("\(optionalString) is nil")
}
However, this runs just fine for me in tests:
var optionalString: String? = "Hello"
// Assigns optionalString to new variable before checking if nil
if optionalString {
println("\(optionalString) is not nil!")
}
else {
println("\(optionalString) is nil")
}
Question
Is there a reason to assign optionalString to a new variable string in the conditional statement?
Take a look at the section on Optional Chaining in the docs. In the example you cite, there's not much difference. But in other cases, an if-let construction lets you get at an unwrapped value that comes from a series of optional references and method calls, without using implicit unwraps that can crash your app if you haven't considered all the possible bindings for a value in a chain.
It's also useful if you want to avoid recomputing a value. You can use it in a lot of the same ways you'd use an assignment in a conditional in (Obj)C (remember if (self = [super init])).
For example, if the optional being tested comes from a computed property:
var optionalName: String? {
get {
if checkTouchID() {
return "John Appleseed"
} else {
return nil
}
}
}
var greeting = "Hello!"
if optionalName != nil {
greeting = "Hello, \(optionalName)"
}
Paste that into a playground, along with a stub implementation of checkTouchID() that returns true, and you'll immediately see in the results area that the optionalName getter is executing twice. (This would be a problem in a more realistic scenario, because you probably don't want code like this to implicitly checkTouchID() or downloadFromServer() or billApplePay() twice.) If you use an if-let construction instead, you'll only execute the getter once.
In a series of chained optionals (like if let johnsStreet = john.residence?.address?.street in the docs linked above), you don't want to rewrite the whole chain in the body of the if statement, much less recompute it.
I think the purpose of that assignment was to demonstrate the use of "let" within the if conditional clause. I don't see a meaningful difference between the provided code and your own.
From: Apple Inc. “The Swift Programming Language.” iBooks. https://itun.es/il/jEUH0.l
“If the optional value is nil, the conditional is false and the code in braces is skipped. Otherwise, the optional value is unwrapped and assigned to the constant after let, which makes the unwrapped value available inside the block of code.”