This question already has an answer here:
Swift Optionals - Different ways of unwrapping
(1 answer)
Closed 8 years ago.
When dealing with an optional in Swift, there are two different ways to access the value behind the optional if it exists. You can do a manual check:
if someOptional != nil {
doSomethingWithValue(someOptional!)
}
else {
//handle nil...
}
or, you can use an if let block to unwrap the optional automatically:
if let unwrapped = someOptional {
doSomethingWithValue(unwrapped)
}
else {
//handle nil...
}
Is one of these options preferable to the other for any reason? Which, if either, is more idiomatic?
EDIT: In response to the close votes, I'm attempting to ask if there is a reason to use one over the other for any reason other than preference, whether it is for performance reasons, safety reasons, or something else.
I think you missed one line of code in your "manual check": Before checking
if someOptional != nil
you'd rather had to assign by something like:
someOptinal : <TypeOptional>? = anyFunctionThatProvidesAnOptional
And therefore this is my opinion: The second way (the so called "optional binding") combines that two lines in one line, so it is shorter and therefore better way.
Related
This question already has answers here:
Swift's guard keyword
(13 answers)
Closed 7 years ago.
I am confused about when to use guard and when to use if...else.
Is guard is replacement or alternative for If statement ?
Main thing want to know what are the functional benefits of guard statement for Swift language?
Any help to clear this situation will be appreciated.
Using guard might not seem much different to using if, but with guard your intention is clearer: execution should not continue if your conditions are not met. Plus it has the advantage of being shorter and more readable, so guard is a real improvement, and I'm sure it will be adopted quickly.
There is one bonus to using guard that might make it even more useful to you: if you use it to unwrap any optionals, those unwrapped values stay around for you to use in the rest of your code block. For example:
guard let unwrappedName = userName else {
return
}
print("Your username is \(unwrappedName)")
This is in comparison to a straight if statement, where the unwrapped value would be available only inside the if block, like this:
if let unwrappedName = userName {
print("Your username is \(unwrappedName)")
} else {
return
}
// this won't work – unwrappedName doesn't exist here!
print("Your username is \(unwrappedName)")
https://www.hackingwithswift.com/swift2
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 7 years ago.
Improve this question
If a variable is an Optional what is the advantage of force unwrapping it.
class Button: UIButton {
var title: UILabel? = nil
required init?(coder aDecoder: NSCoder) {
fatalError()
}
override init(frame: CGRect) {
super.init(frame: frame)
}
func addTitle(text: String) {
title = UILabel(frame: CGRect())
self.addSubview(title!)
}
}
let a: Button = Button(frame: CGRect())
a.addTitle("Hello World")
// Case 1
a.title?.text = "Goodbye"
// Case 2
a.title!.text = "Hello World"
Question
In Case 1 I know its safer but is there any performance improvements or reason to use Case 2?
So, if we know that Case 1 is more safe why should we ever use Case 2?
Performance-wise there might be a very to very very small no difference between forced and optional binding/chaining, as the optional version might have an extra if somewhere.
But nonetheless when talking about performance issues, the performance bottlenecks come from other parts of the code, like non-improved loops, lots of accumulation NSNotification's sent in a short amount of time, unnecessary redraws of the UI, etc.
So it's best to stay on the safer side and use optional binding/casting/chaining and focus on the parts of the code that adds actual performance penalties. Even if at the time you write the code the value is guaranteed to be non-nil, in the future in might be that the conditions will change and you'll suddenly end up with crashes that you didn't expect they'll occur.
Swift has made it very easy to deal with optionals, without writing a lot of boilerplate code, you should take advantage of those features.
As per the comment, your example isn't actually valid. Putting that aside: force unwrapping means "I work only with a concrete value; I want to fail immediately if I don't have one". So it's often preferable to proceeding through that section of code with a nil value and then having some other problem sometime later once the causal nexus has been substantially eroded.
So: it allows you to be explicit about who owns responsibility for guaranteeing that a value is present.
Good (or at least defensible) reasons to use implicitly unwrapped Optionals, or to force unwrap an Optional using !:
#IBOutlets: These are normally implicitly unwrapped for a couple of reasons. You don't want to have to manually unwrap them every time you access them. But more importantly, if your outlets aren't hooked up right, you want to know immediately.
Other instances where you make a conscious decision that you want the app to crash if a value is nil. For example, if you are instantiating a view controller from a storyboard and it is required to be a particular subclass of UIViewController called MyViewController in order for your app to function at all, you might force cast it using return vc as! MyViewController. That way you discover right away that something is off.
Honestly, that's it, as far as I can tell. Just my own approach, but I reserve the ! for declaring #IBOutlets. Otherwise, 99.999% of the time I unwrap with if let or guard, or ? in an an optional chaining situation. There are other ways to know that the value is nil. If the optional fails to unwrap, print a message to the console telling you that it failed. To me, a short descriptive message is easier to debug than a crash and an unexpectedly found nil while unwrapping an optional value error. If I want the program to fail, I can still use fatalError with a descriptive message:
guard let x = someOptional else { fatalError("someOptional is nil in awakeFromNib.") }
By reserving ! for #IBOutlets, every time I get one of those unexpectedly found nil while unwrapping an optional value errors I know exactly where to look to find the source of my problem. I look at my #IBOutlet connections in interface builder. Sticking to that policy, and using other tools to identify other values that are nil when they shouldn't be, works for me.
Some alternatives (avoid force unwrapping !). Try these out using an non-nil value of a as well as when a contains nil.
var a: String? = nil
a = "Hello World"
// Case 1 : nil coalescing operator
print(a ?? "a has value nil, let's not unwrap it!")
// Case 2 : if-let clause
if let a = a {
print(a)
}
else {
print("a has value nil, let's not unwrap it!")
}
// Case 3 : guard-let-else clause
func foo(a: String?) {
guard let a = a else {
print("a has value nil, let's not unwrap it!")
return
}
print(a)
}
foo(a)
This question already has answers here:
println dictionary has "Optional"
(2 answers)
Closed 7 years ago.
If the following code runs
var airports = ["YYZ": "Toronto Pearson", "DUB": "Dublin"]
print(airports["YYZ"])
Why does the console print
Optional("Toronto Pearson")
Why does it print Optional( withValue ) and not just the value?
Why would I need to know that in the console?
Swift has optional types for operations that may fail. An array index like airports["XYZ"] is an example of this. It will fail if the index is not found. This is in lieu of a nil type or exception.
The simplest way to unwrap an optional type is to use an exclamation point, like so: airports["XYZ"]!. This will cause a panic if the value is nil.
Here's some further reading.
You can chain methods on option types in Swift, which will early exit to a nil without calling a method if the lefthand value is nil. It works when you insert a question mark between the value and method like this: airports["XYZ"]?.Method(). Because the value is nil, Method() is never called. This allows you to delay the decision about whether to deal with an optional type, and can clean up your code a bit.
To safely use an optional type without panicking, just provide an alternate path using an if statement.
if let x:String? = airports["XYZ"] {
println(x!)
} else {
println("airport not found")
}
I'm very new to swift, but proficient in other languages like Java, JavaScript, C, ... I'm lost with Swift syntax when it comes to create expressions. Look at this basic example where I just try to find out if one string is contained into another by calling String.rangeOfString that returns an Optional Range (Range?)
This works as expected:
let LEXEMA:String="http://"
let longUrl:String="http://badgirls.many/picture.png"
let range=longUrl.rangeOfString(LEXEMA);
if (range? != nil) {
// blah
}
Now I'm trying to combine the expression inside the if, something like:
if (longUrl.rangeOfString(LEXEMA)? !=nil) {
// blah
}
But I always get syntax errors, the above yields a "Expected Separator" and can't understand why. Done some more tests:
if (absolutePath.rangeOfString(URL_LEXEMA) !=nil) { }
Expected Separator before "!"
if absolutePath.rangeOfString(URL_LEXEMA) !=nil { }
Braced block of statements is an unused closure
What am I doing wrong?
If you’re coming from other like Java, you might be thinking of optionals like pointers/references, and so used to equating them to nil and if non-nil, using them. But this is probably going to lead to more confusion. Instead, think of them like a container for a possible result, that you need to unwrap to use. if let combines the test and unwrapping operation.
With this in mind, here’s how you could adapt your code:
let LEXEMA: String="http://"
let longUrl: String="http://badgirls.many/picture.png"
if let range = longUrl.rangeOfString(LEXEMA) {
// use range, which will be the unwrapped non-optional range
}
else {
// no such range, perhaps log an error if this shouldn’t happen
}
Note, that ? suffixing behaviour you were using changes in Swift 1.2 so even the code in your question that compiles in 1.1 won’t in 1.2.
It’s possible that sometimes you are whether there was a value returned, but you don’t actually need that value, just to know it wasn’t nil. In that case, you can compare the value to nil without the let:
if longUrl.rangeOfString(LEXEMA) != nil {
// there was a value, but you don't care what that value was
}
That said, the above is probably better expressed as:
if longUrl.hasPrefix(LEXEMA) { }
For starters:
You don't need parenthesis with if statements unless you have nested parenthetical subexpressions that require it.
You don't need to specify the type on the left side of the = of a let or var declaration if Swift can figure it out from the right side of the =. Very often Swift can figure it out, and you can tell that Swift can figure it out, so you can avoid that redundant clutter.
You do need to specify the type if Swift cannot figure out the type from
the right side. Example:
For example, consider the following lines:
let LEXEMA = "http://"
let longUrl = "http://badgirls.many/picture.png"
Swift can figure out that they're strings.
Similarly for this function or class that returns a UIView:
var myView = ViewReturningClassOrFunc()
Consider this:
#IBOutlet var myView : UIView!
In the above line, Swift cannot figure out ahead of time it will be assigned a UIView, so you have to provide the type. By providing a ! at the end you've made it an implicitly unwrapped optional. That means, like ?, you're indicating that it can be nil, but that you are confident it will never be nil at the time you access it, so Swift won't require you to put a ! after it when you reference it. That trick is a time saver and big convenience.
You should NOT add the ? to the line:
if (longUrl.rangeOfString(URL_LEXEMA) !=nil) {
As another answer pointed out, you're missing the let.
if let longUrl.rangeOfString(URL_LEXEMA) {
println("What do I win? :-)")
}
swift is case sensitive language. you need to check about whitespaces as well
if longUrl.rangeOfString(LEXEMA) != nil {
//your condition
}
there should be space between statement != nil
Just add a space between != and nil like:
if longUrl.rangeOfString(LEXEMA) != nil {
// blah
}
I tested your code in playground, an error of Expected ',' separator reported.
And do not forget the rules that 1s and 0s and Airspeed Velocity said.
Numerously in the past I have fixed the sporadic unexpectedly found nil while unwrapping an Optional value error, and I have just fixed one now; However the way I am doing it right now is through guessing where the nil optionals are via breakpoints.
There is always an EXC_BREAKPOINT under Swift._fatalErrorMessage (in the assembly) when an error like this is thrown for me.
Is there a more efficient method (like a exception catch) of jumping to the nil optional instead of guessing where it is with log messages and (inline) breakpoints?
Your crashes are almost certainly happening in a line where you're forcibly unwrapping an optional using !. Unless you're absolutely certain that a value exists, you should use if let instead.
Instead of:
let myValue = myArray[index]! // will crash if myArray[index] is nil
Use this:
if let myValue = myArray[index] {
println("myValue has a value and it is \(myValue)")
// Code using myValue
} else {
println("myValue is nil")
}
Edit: To answer your question directly, search for instances of ! and in general, replace them with if let or ?.