Two (or more) optionals in Swift - ios

While watching an Apple's video about LLDB debugger I found something I can't find an explanation for; he was talking about optional values when he wrote:
var optional: String? = nil; //This is ok, a common optional
var twice_optional: String?? = nil; //What is this and why's this useful??
I opened a playground and started trying it out and realized that you can write as many as ? as you want, and then unwrap them with the same number of !. I understand the concept of wrapping/unwrapping a variable but can't think of a situation where I would like to wrap a value 4, 5 or 6 times.

(Updated for Swift >=3)
"Double optionals" can be useful, and the Swift blog entry "Optionals Case Study: valuesForKeys" describes an application.
Here is a simplified example:
let dict : [String : String?] = ["a" : "foo" , "b" : nil]
is a dictionary with optional strings as values. Therefore
let val = dict[key]
has the type String?? aka Optional<Optional<String>>. It is .none (or nil)
if the key is not present in the dictionary, and .some(x) otherwise. In the second
case, x is a String? aka Optional<String> and can be .none (or nil)
or .some(s) where s is a String.
You can use nested optional binding to check for the various cases:
for key in ["a", "b", "c"] {
let val = dict[key]
if let x = val {
if let s = x {
print("\(key): \(s)")
} else {
print("\(key): nil")
}
} else {
print("\(key): not present")
}
}
Output:
a: foo
b: nil
c: not present
It might be instructive to see how the same can be achieved with pattern matching
in a switch-statement:
let val = dict[key]
switch val {
case .some(.some(let s)):
print("\(key): \(s)")
case .some(.none):
print("\(key): nil")
case .none:
print("\(key): not present")
}
or, using the x? pattern as a synonym for .some(x):
let val = dict[key]
switch val {
case let (s??):
print("\(key): \(s)")
case let (s?):
print("\(key): nil")
case nil:
print("\(key): not present")
}
(I do not know a sensible application for more deeply nested optionals.)

var tripleOptional: String???
is same as
var tripleOptional: Optional<Optional<Optional<String>>>
I cannot think of any useful use of it, but its there because optionals are generic work for any type of object. Nested optionals are like box put into another box or array but into an other array.

Related

How do I check for null when unwrapping optionals from a Swift dictionary? [duplicate]

I have the following code in a playground file:
extension Dictionary {
func test() {
for key in self.keys {
self[key]
}
}
}
var dict: [String: AnyObject?] = [
"test": nil
]
dict.test()
I will henceforth refer to the line within the for-each loop as the output since it is what's relevant. In this particular instance the output is nil.
When I change the for-each loop to look like this:
for key in self.keys {
print(self[key])
}
The output is "Optional(nil)\n".
What I really want to do is check the value for nil, but the code:
for key in self.keys {
self[key] == nil
}
outputs false.
One other thing I tried was the following:
for key in self.keys {
self[key] as! AnyObject? == nil
}
which produces the error:
Could not cast value of type 'Swift.Optional<Swift.AnyObject>' to 'Swift.AnyObject'
Any help with this is much appreciated!
You've gotten yourself into kind a mess, because a dictionary whose values can be nil presents you with the prospect of a double-wrapped Optional, and therefore two kinds of nil. There is the nil that you get if the key is missing, and then the nil that you get if the key is not missing and you unwrap the fetched result. And unfortunately, you're testing in a playground, which is a poor venue for exploring the distinction.
To see what I mean, consider just the following:
var d : [String:Int?] = ["Matt":1]
let val = d["Matt"]
What is the type of val? It's Int?? - an Int wrapped in an Optional wrapped in another Optional. That's because the value inside the dictionary was, by definition, an Int wrapped in an Optional, and then fetching the value by its key wraps that in another Optional.
So now let's go a bit further and do it this way:
var d : [String:Int?] = ["Matt":nil]
let val = d["Matt"]
What is val? Well, the playground may say it is nil, but the truth is more complicated; it's nil wrapped in another Optional. That is easiest to see if you print val, in which case you get, not nil, but "Optional(nil)".
But if we try for something where the key isn't there at all, we get a different answer:
let val2 = d["Alex"]
That really is nil, signifying that the key is missing. And if we print val2, we get "nil". The playground fails to make the distinction (it says nil for both val and val2), but converting to a String (which is what print does) shows the difference.
So part of the problem is this whole double-wrapped Optional thing, and the other part is that the Playground represents a double-wrapped Optional in a very misleading way.
MORAL 1: A dictionary whose value type is an Optional can get really tricky.
MORAL 2: Playgrounds are the work of the devil. Avoid them. Use a real app, and use logging to the console, or the variables pane of the debugger, to see what's really happening.
Checking if a dictionary value is nil makes sense only if the
dictionary values are an Optional type, which means that you have to
restrict your extension method to that case.
This is possible by defining a protocol that all optional types conform
to (compare How can I write a function that will unwrap a generic property in swift assuming it is an optional type?, which is just a slight modification of Creating an extension to filter nils from an Array in Swift):
protocol OptionalType {
typealias Wrapped
var asOptional : Wrapped? { get }
}
extension Optional : OptionalType {
var asOptional : Wrapped? {
return self
}
}
Now you can define an extension method with is restricted to
dictionaries of optional value types:
extension Dictionary where Value : OptionalType {
func test() {
for key in self.keys { ... }
}
}
As Matt already explained, self[key] can only be nil if that key
is missing in the dictionary, and that can not happen here. So you
can always retrieve the value for that key
let value = self[key]!
inside that loop. Better, enumerate over keys and values:
for (key, value) in self { ... }
Now value is the dictionary value (for key), and its type
conforms to OptionalType. Using the asOptional protocol property
you get an optional which can be tested against nil:
if value.asOptional == nil { ... }
or used with optional binding.
Putting all that together:
extension Dictionary where Value : OptionalType {
func test() {
for (key, value) in self {
if let unwrappedValue = value.asOptional {
print("Unwrapped value for '\(key)' is '\(unwrappedValue)'")
} else {
print("Value for '\(key)' is nil")
}
}
}
}
Example:
var dict: [String: AnyObject?] = [
"foo" : "bar",
"test": nil
]
dict.test()
Output:
Value for 'test' is nil
Unwrapped value for 'foo' is 'bar'

Understanding the logic of an if let statement - variable used before being initialized

So I'm following a tutorial on udemy and have this piece of code.
let itemsObject = UserDefaults.standard.object(forKey: "items")
var items:[String]
if let tempItems = itemsObject as? [String]
{
//
items = tempItems
items.append(textfield.text!)
}
I understand the itemsObject and items array but I'm wondering why I'm not able to bypass the tempItems constant altogether like...
var items:[String]
if items = itemsObject as? [String]
{
items.append(textfield.text!)
}
I don't understand the purpose of the let tempItems constant.
let itemsObject = UserDefaults.standard.object(forKey: "items")
itemsObject is now of type Any? So we need to do 2 things: cast it and check if it's nil
if let tempItems = itemsObject as? [String]
is a shortcut for:
let tempItems1 = itemsObject as? [String] // cast to [String]?
if tempItems1 != nil {
let tempItems2 = tempItems1! // we know its not nil, so force unwrap it to [String]
...
}
Hint:
[String]? is a string array that can be nil
[String] is a string array that can't be nil
Optional binding is value-binding pattern matching, which is not equivalent to assignment
Consider the following simplified example:
let foo: Any = 1
if let bar = foo as? Int { /* ... */ }
So what are we doing in the last row here? We attempt to conditionally convert an Any instance (foo) to the type Int. The result of such an conditional type conversion (as?) is an Optional:
foo as? Int // type: Optional<Int>
Moving on, we try to optionally bind the possibly successful conversion to an immutable concrete instance of type Int (the bar property). See optional binding in the language guide for details.
Now, the way we perform optional binding is simply syntactic sugar for value-binding pattern matching, in the context of (given successful pattern match) attempting to bind an associated value of an enum case to a property. The syntactic sugar of optional binding is available to the extremly common Optional<Wrapped> enum type, whereas for other enum type, we need to use the common value-binding pattern syntax
if case let .anEnumCase(bindAssociatedValueToMe) = someEnumInstance { /* ... */ }
// alternatively
if case .anEnumCase(let bindAssociatedValueToMe) = someEnumInstance { /* ... */ }
I.e., the following two (three) are equivalent
// make use of syntactic sugar available for `Optional` enum
if let bar = foo as? Int { /* .. */ }
// or use the explicit value-binding pattern available to any
// enum with a case that holds and associated value
if case .some(let bar) = foo as? Int { /* .. */ }
// (for the latter: alternatively)
if case let .some(bar) = foo as? Int { /* .. */ }
And, to add some extra confusion to the matter, we also have another special syntactic sugar available to the special enum Optional<Wrapped> (the .some(let bindWrappedToThis) case, specifically), such that also the following is equivalent to the two above:
// using the sugar '_?' instead of '.some(_)', here replacing
// '... let .some(bar)' with '... let bar?'
if case let bar? = foo as? Int { /* .. */ }
The key to understanding the above is to understand the following:
An attempted type conversion, using as?, will result in an Optional<Wrapped> instance with the Wrapped type being the target type of the type conversion. I.e., someInstance as? SomeType will result in an instance of Optional<SomeType>, that may be nil (.none), or may be wrapping a concrete instance of SomeType (.some(someInstanceOfSomeType)).
The type Optional<Wrapped> in Swift is, when leaving out all the special neatness/sugar, an enumeration,
Finally, that value-binding pattern matching is not the same as assignment.
1) is self-explanatory by its thorough description. To understand 2) & 3), we may study the following simple example, showing a custom "optional"-like enum with a case that holds a generic associated value, which, for a given instance of the enum, we try to conditionally bind to a property:
enum MyOptional<Wrapped> {
case none
case some(Wrapped)
}
// instantiate with a case with an associated value
let foo = MyOptional.some(1) // MyOptional<Int>.some(1)
// use value-binding pattern matching to conditionally
// access the associated value of the 'some(...)' case,
// given that 'foo' is '.some' (and not '.none')
if case .some(let bar) = foo { /* .. */ }
Notice the value-binding in the last line above, and compare to the non-sugared optional binding in the previous code snippet above.
Finally, note that you have means other than optional binding to access and perform operations on the (possible existing) wrapped value of an optional. E.g. using the map(_:) method of Optional, at the cost of clarity, we could condense your example (as well as make items immutable) in your top code snippet to the following:
let items = (UserDefaults.standard.object(forKey: "items") as? [String])
.map { $0 + [textfield.text!] } ?? []
Which, in a single expressions, make use of the following:
conditional type conversion of the UserDefaults value to type [String]
in case of successful type conversion, append textField.text! to the concrete [String] value and assign to items
in case of unsuccessful type conversion, use the nil coalescing operator ?? to supply and empty array, [], as a default value to items.

When should I compare an optional value to nil?

Quite often, you need to write code such as the following:
if someOptional != nil {
// do something with the unwrapped someOptional e.g.
someFunction(someOptional!)
}
This seems a bit verbose, and also I hear that using the ! force unwrap operator can be unsafe and best avoided. Is there a better way to handle this?
It is almost always unnecessary to check if an optional is not nil. Pretty much the only time you need to do this is if its nil-ness is the only thing you want to know about – you don’t care what’s in the value, just that it’s not nil.
Under most other circumstances, there is a bit of Swift shorthand that can more safely and concisely do the task inside the if for you.
Using the value if it isn’t nil
Instead of:
let s = "1"
let i = Int(s)
if i != nil {
print(i! + 1)
}
you can use if let:
if let i = Int(s) {
print(i + 1)
}
You can also use var:
if var i = Int(s) {
print(++i) // prints 2
}
but note that i will be a local copy - any changes to i will not affect the value inside the original optional.
You can unwrap multiple optionals within a single if let, and later ones can depend on earlier ones:
if let url = NSURL(string: urlString),
data = NSData(contentsOfURL: url),
image = UIImage(data: data)
{
let view = UIImageView(image: image)
// etc.
}
You can also add where clauses to the unwrapped values:
if let url = NSURL(string: urlString) where url.pathExtension == "png",
let data = NSData(contentsOfURL: url), image = UIImage(data: data)
{ etc. }
Replacing nil with a default
Instead of:
let j: Int
if i != nil {
j = i
}
else {
j = 0
}
or:
let j = i != nil ? i! : 0
you can use the nil-coalescing operator, ??:
// j will be the unwrapped value of i,
// or 0 if i is nil
let j = i ?? 0
Equating an optional with a non-optional
Instead of:
if i != nil && i! == 2 {
print("i is two and not nil")
}
you can check if optionals are equal to non-optional values:
if i == 2 {
print("i is two and not nil")
}
This also works with comparisons:
if i < 5 { }
nil is always equal to other nils, and is less than any non-nil value.
Be careful! There can be gotchas here:
let a: Any = "hello"
let b: Any = "goodbye"
if (a as? Double) == (b as? Double) {
print("these will be equal because both nil...")
}
Calling a method (or reading a property) on an optional
Instead of:
let j: Int
if i != nil {
j = i.successor()
}
else {
// no reasonable action to take at this point
fatalError("no idea what to do now...")
}
you can use optional chaining, ?.:
let j = i?.successor()
Note, j will also now be optional, to account for the fatalError scenario. Later, you can use one of the other techniques in this answer to handle j’s optionality, but you can often defer actually unwrapping your optionals until much later, or sometimes not at all.
As the name implies, you can chain them, so you can write:
let j = s.toInt()?.successor()?.successor()
Optional chaining also works with subscripts:
let dictOfArrays: ["nine": [0,1,2,3,4,5,6,7]]
let sevenOfNine = dictOfArrays["nine"]?[7] // returns {Some 7}
and functions:
let dictOfFuncs: [String:(Int,Int)->Int] = [
"add":(+),
"subtract":(-)
]
dictOfFuncs["add"]?(1,1) // returns {Some 2}
Assigning to a property on an optional
Instead of:
if splitViewController != nil {
splitViewController!.delegate = self
}
you can assign through an optional chain:
splitViewController?.delegate = self
Only if splitViewController is non-nil will the assignment happen.
Using the value if it isn’t nil, or bailing (new in Swift 2.0)
Sometimes in a function, there’s a short bit of code you want to write to check an optional, and if it’s nil, exit the function early, otherwise keep going.
You might write this like this:
func f(s: String) {
let i = Int(s)
if i == nil { fatalError("Input must be a number") }
print(i! + 1)
}
or to avoid the force unwrap, like this:
func f(s: String) {
if let i = Int(s) {
print(i! + 1)
}
else {
fatalErrr("Input must be a number")
}
}
but it’s much nicer to keep the error-handling code at the top by the check. This can also lead to unpleasant nesting (the "pyramid of doom").
Instead you can use guard, which is like an if not let:
func f(s: String) {
guard let i = Int(s)
else { fatalError("Input must be a number") }
// i will be an non-optional Int
print(i+1)
}
The else part must exit the scope of the guarded value, e.g. a return or fatalError, to guarantee that the guarded value will be valid for the remainder of the scope.
guard isn’t limited to function scope. For example the following:
var a = ["0","1","foo","2"]
while !a.isEmpty {
guard let i = Int(a.removeLast())
else { continue }
print(i+1, appendNewline: false)
}
prints 321.
Looping over non-nil items in a sequence (new in Swift 2.0)
If you have a sequence of optionals, you can use for case let _? to iterate over all the non-optional elements:
let a = ["0","1","foo","2"]
for case let i? in a.map({ Int($0)}) {
print(i+1, appendNewline: false)
}
prints 321. This is using the pattern-matching syntax for an optional, which is a variable name followed by ?.
You can also use this pattern matching in switch statements:
func add(i: Int?, _ j: Int?) -> Int? {
switch (i,j) {
case (nil,nil), (_?,nil), (nil,_?):
return nil
case let (x?,y?):
return x + y
}
}
add(1,2) // 3
add(nil, 1) // nil
Looping until a function returns nil
Much like if let, you can also write while let and loop until nil:
while let line = readLine() {
print(line)
}
You can also write while var (similar caveats to if var apply).
where clauses also work here (and terminate the loop, rather than skipping):
while let line = readLine()
where !line.isEmpty {
print(line)
}
Passing an optional into a function that takes a non-optional and returns a result
Instead of:
let j: Int
if i != nil {
j = abs(i!)
}
else {
// no reasonable action to take at this point
fatalError("no idea what to do now...")
}
you can use optional’s map operator:
let j = i.map { abs($0) }
This is very similar to optional chaining, but for when you need to pass the non-optional value into the function as an argument. As with optional chaining, the result will be optional.
This is nice when you want an optional anyway. For example, reduce1 is like reduce, but uses the first value as the seed, returning an optional in case the array is empty. You might write it like this (using the guard keyword from earlier):
extension Array {
func reduce1(combine: (T,T)->T)->T? {
guard let head = self.first
else { return nil }
return dropFirst(self).reduce(head, combine: combine)
}
}
[1,2,3].reduce1(+) // returns 6
But instead you could map the .first property, and return that:
extension Array {
func reduce1(combine: (T,T)->T)->T? {
return self.first.map {
dropFirst(self).reduce($0, combine: combine)
}
}
}
Passing an optional into a function that takes an optional and returns a result, avoiding annoying double-optionals
Sometimes, you want something similar to map, but the function you want to call itself returns an optional. For example:
// an array of arrays
let arr = [[1,2,3],[4,5,6]]
// .first returns an optional of the first element of the array
// (optional because the array could be empty, in which case it's nil)
let fst = arr.first // fst is now [Int]?, an optional array of ints
// now, if we want to find the index of the value 2, we could use map and find
let idx = fst.map { find($0, 2) }
But now idx is of type Int??, a double-optional. Instead, you can use flatMap, which “flattens” the result into a single optional:
let idx = fst.flatMap { find($0, 2) }
// idx will be of type Int?
// and not Int?? unlike if `map` was used
I think you should go back to the Swift programming book and learn what these things are for. ! is used when you are absolutely sure that the optional isn't nil. Since you declared that you are absolutely sure, it crashes if you're wrong. Which is entirely intentional. It is "unsafe and best avoided" in the sense that asserts in your code are "unsafe and best avoided". For example:
if someOptional != nil {
someFunction(someOptional!)
}
The ! is absolutely safe. Unless there is a big blunder in your code, like writing by mistake (I hope you spot the bug)
if someOptional != nil {
someFunction(SomeOptional!)
}
in which case your app may crash, you investigate why it crashes, and you fix the bug - which is exactly what the crash is there for. One goal in Swift is that obviously your app should work correctly, but since Swift cannot enforce this, it enforces that your app either works correctly or crashes if possible, so bugs get removed before the app ships.
You there is one way. It is called Optional Chaining. From documentation:
Optional chaining is a process for querying and calling properties,
methods, and subscripts on an optional that might currently be nil. If
the optional contains a value, the property, method, or subscript call
succeeds; if the optional is nil, the property, method, or subscript
call returns nil. Multiple queries can be chained together, and the
entire chain fails gracefully if any link in the chain is nil.
Here is some example
class Person {
var residence: Residence?
}
class Residence {
var numberOfRooms = 1
}
let john = Person()
if let roomCount = john.residence?.numberOfRooms {
println("John's residence has \(roomCount) room(s).")
} else {
println("Unable to retrieve the number of rooms.")
}
// prints "Unable to retrieve the number of rooms."
You can check the full article here.
We can use optional binding.
var x:Int?
if let y = x {
// x was not nil, and its value is now stored in y
}
else {
// x was nil
}
After lot of thinking and researching i have came up with the easiest way to unwrap an optional :
Create a new Swift File and name it UnwrapOperator.swift
Paste the following code in the file :
import Foundation
import UIKit
protocol OptionalType { init() }
extension String: OptionalType {}
extension Int: OptionalType {}
extension Int64: OptionalType {}
extension Float: OptionalType {}
extension Double: OptionalType {}
extension CGFloat: OptionalType {}
extension Bool: OptionalType {}
extension UIImage : OptionalType {}
extension IndexPath : OptionalType {}
extension NSNumber : OptionalType {}
extension Date : OptionalType {}
extension UIViewController : OptionalType {}
postfix operator *?
postfix func *?<T: OptionalType>( lhs: T?) -> T {
guard let validLhs = lhs else { return T() }
return validLhs
}
prefix operator /
prefix func /<T: OptionalType>( rhs: T?) -> T {
guard let validRhs = rhs else { return T() }
return validRhs
}
Now the above code has created 2 operator [One prefix and one postfix].
At the time of unwrapping you can use either of these operator before or after the optionals
The explanation is simple, the operators returns the constructor value if they get nil in variable else the contained value inside the variable.
Below is the example of usage :
var a_optional : String? = "abc"
var b_optional : Int? = 123
// before the usage of Operators
print(a_optional) --> Optional("abc")
print(b_optional) --> Optional(123)
// Prefix Operator Usage
print(/a_optional) --> "abc"
print(/b_optional) --> 123
// Postfix Operator Usage
print(a_optional*?) --> "abc"
print(b_optional*?) --> 123
Below is the example when variable contains nil :
var a_optional : String? = nil
var b_optional : Int? = nil
// before the usage of Operators
print(a_optional) --> nil
print(b_optional) --> nil
// Prefix Operator Usage
print(/a_optional) --> ""
print(/b_optional) --> 0
// Postfix Operator Usage
print(a_optional*?) --> ""
print(b_optional*?) --> 0
Now it is your choice which operator you use, both serve the same purpose.

Swift: Testing optionals for nil

I'm using Xcode 6 Beta 4. I have this weird situation where I cannot figure out how to appropriately test for optionals.
If I have an optional xyz, is the correct way to test:
if (xyz) // Do something
or
if (xyz != nil) // Do something
The documents say to do it the first way, but I've found that sometimes, the second way is required, and doesn't generate a compiler error, but other times, the second way generates a compiler error.
My specific example is using the GData XML parser bridged to swift:
let xml = GDataXMLDocument(
XMLString: responseBody,
options: 0,
error: &xmlError);
if (xmlError != nil)
Here, if I just did:
if xmlError
it would always return true. However, if I do:
if (xmlError != nil)
then it works (as how it works in Objective-C).
Is there something with the GData XML and the way it treats optionals that I am missing?
In Xcode Beta 5, they no longer let you do:
var xyz : NSString?
if xyz {
// Do something using `xyz`.
}
This produces an error:
does not conform to protocol 'BooleanType.Protocol'
You have to use one of these forms:
if xyz != nil {
// Do something using `xyz`.
}
if let xy = xyz {
// Do something using `xy`.
}
To add to the other answers, instead of assigning to a differently named variable inside of an if condition:
var a: Int? = 5
if let b = a {
// do something
}
you can reuse the same variable name like this:
var a: Int? = 5
if let a = a {
// do something
}
This might help you avoid running out of creative variable names...
This takes advantage of variable shadowing that is supported in Swift.
Swift 3.0, 4.0
There are mainly two ways of checking optional for nil. Here are examples with comparison between them
1. if let
if let is the most basic way to check optional for nil. Other conditions can be appended to this nil check, separated by comma. The variable must not be nil to move for the next condition. If only nil check is required, remove extra conditions in the following code.
Other than that, if x is not nil, the if closure will be executed and x_val will be available inside. Otherwise the else closure is triggered.
if let x_val = x, x_val > 5 {
//x_val available on this scope
} else {
}
2. guard let
guard let can do similar things. It's main purpose is to make it logically more reasonable. It's like saying Make sure the variable is not nil, otherwise stop the function. guard let can also do extra condition checking as if let.
The differences are that the unwrapped value will be available on same scope as guard let, as shown in the comment below. This also leads to the point that in else closure, the program has to exit the current scope, by return, break, etc.
guard let x_val = x, x_val > 5 else {
return
}
//x_val available on this scope
One of the most direct ways to use optionals is the following:
Assuming xyz is of optional type, like Int? for example.
if let possXYZ = xyz {
// do something with possXYZ (the unwrapped value of xyz)
} else {
// do something now that we know xyz is .None
}
This way you can both test if xyz contains a value and if so, immediately work with that value.
With regards to your compiler error, the type UInt8 is not optional (note no '?') and therefore cannot be converted to nil. Make sure the variable you're working with is an optional before you treat it like one.
From swift programming guide
If Statements and Forced Unwrapping
You can use an if statement to find out whether an optional contains a
value. If an optional does have a value, it evaluates to true; if it
has no value at all, it evaluates to false.
So the best way to do this is
// swift > 3
if xyz != nil {}
and if you are using the xyz in if statement.Than you can unwrap xyz in if statement in constant variable .So you do not need to unwrap every place in if statement where xyz is used.
if let yourConstant = xyz {
//use youtConstant you do not need to unwrap `xyz`
}
This convention is suggested by apple and it will be followed by devlopers.
Although you must still either explicitly compare an optional with nil or use optional binding to additionally extract its value (i.e. optionals are not implicitly converted into Boolean values), it's worth noting that Swift 2 has added the guard statement to help avoid the pyramid of doom when working with multiple optional values.
In other words, your options now include explicitly checking for nil:
if xyz != nil {
// Do something with xyz
}
Optional binding:
if let xyz = xyz {
// Do something with xyz
// (Note that we can reuse the same variable name)
}
And guard statements:
guard let xyz = xyz else {
// Handle failure and then exit this code block
// e.g. by calling return, break, continue, or throw
return
}
// Do something with xyz, which is now guaranteed to be non-nil
Note how ordinary optional binding can lead to greater indentation when there is more than one optional value:
if let abc = abc {
if let xyz = xyz {
// Do something with abc and xyz
}
}
You can avoid this nesting with guard statements:
guard let abc = abc else {
// Handle failure and then exit this code block
return
}
guard let xyz = xyz else {
// Handle failure and then exit this code block
return
}
// Do something with abc and xyz
Swift 5 Protocol Extension
Here is an approach using protocol extension so that you can easily inline an optional nil check:
import Foundation
public extension Optional {
var isNil: Bool {
guard case Optional.none = self else {
return false
}
return true
}
var isSome: Bool {
return !self.isNil
}
}
Usage
var myValue: String?
if myValue.isNil {
// do something
}
if myValue.isSome {
// do something
}
One option that hasn't specifically been covered is using Swift's ignored value syntax:
if let _ = xyz {
// something that should only happen if xyz is not nil
}
I like this since checking for nil feels out of place in a modern language like Swift. I think the reason it feels out of place is that nil is basically a sentinel value. We've done away with sentinels pretty much everywhere else in modern programming so nil feels like it should go too.
Instead of if, ternary operator might come handy when you want to get a value based on whether something is nil:
func f(x: String?) -> String {
return x == nil ? "empty" : "non-empty"
}
Another approach besides using if or guard statements to do the optional binding is to extend Optional with:
extension Optional {
func ifValue(_ valueHandler: (Wrapped) -> Void) {
switch self {
case .some(let wrapped): valueHandler(wrapped)
default: break
}
}
}
ifValue receives a closure and calls it with the value as an argument when the optional is not nil. It is used this way:
var helloString: String? = "Hello, World!"
helloString.ifValue {
print($0) // prints "Hello, World!"
}
helloString = nil
helloString.ifValue {
print($0) // This code never runs
}
You should probably use an if or guard however as those are the most conventional (thus familiar) approaches used by Swift programmers.
Optional
Also you can use Nil-Coalescing Operator
The nil-coalescing operator (a ?? b) unwraps an optional a if it contains a value, or returns a default value b if a is nil. The expression a is always of an optional type. The expression b must match the type that is stored inside a.
let value = optionalValue ?? defaultValue
If optionalValue is nil, it automatically assigns value to defaultValue
Now you can do in swift the following thing which allows you to regain a little bit of the objective-c if nil else
if textfieldDate.text?.isEmpty ?? true {
}
var xyz : NSDictionary?
// case 1:
xyz = ["1":"one"]
// case 2: (empty dictionary)
xyz = NSDictionary()
// case 3: do nothing
if xyz { NSLog("xyz is not nil.") }
else { NSLog("xyz is nil.") }
This test worked as expected in all cases.
BTW, you do not need the brackets ().
If you have conditional and would like to unwrap and compare, how about taking advantage of the short-circuit evaluation of compound boolean expression as in
if xyz != nil && xyz! == "some non-nil value" {
}
Granted, this is not as readable as some of the other suggested posts, but gets the job done and somewhat succinct than the other suggested solutions.
If someone is also try to find to work with dictionaries and try to work with Optional(nil).
let example : [Int:Double?] = [2: 0.5]
let test = example[0]
You will end up with the type Double??.
To continue on your code, just use coalescing to get around it.
let example : [Int:Double?] = [2: 0.5]
let test = example[0] ?? nil
Now you just have Double?
This is totally logical, but I searched the wrong thing, maybe it helps someone else.
Since Swift 5.7:
if let xyz {
// Do something using `xyz` (`xyz` is not optional here)
} else {
// `xyz` was nil
}

Swift closure as values in Dictionary

I'm trying to use an Objective-C library which expects a NSDictionary as its return type. Within the NSDictionary, I can return values of any type, including blocks.
I cannot figure out if there is a way to write an analogous swift method that returns a Dictionary with a closure or a string as a possible value type.
I can't use AnyObject as the value type for the dictionary so this doesn't work:
Dictionary<String,AnyObject> = ["Key":{(value:AnyObject) -> String in return value.description]
I get a Does not conform to protocol error from the compiler regarding the closure and AnyObject.
Is there a higher level type or protocol that both closures and basic types adhere to that I can use as the value type in a Dictionary?
Your basic problem is that in Objective-C closures (aka blocks) are represented as NSObject (or more precisely are transparently converted to NSObjects) while in Swift there is no such mapping. This means that closures can not be directly stored in a Dictionary (short of using objective-c glue)
The closest I can come up with is something along the lines of wrapping the value in an enum:
enum DataType {
case AsString(String)
case AsClosure((AnyObject)->String)
}
var dict:Dictionary<String,DataType> = [
"string":DataType.AsString("value"),
"closure":DataType.AsClosure({(argument:AnyObject) -> String in
return "value"
}
)
]
Which is probably a better solution anyway, because this way you have an explicit typing associated with individual arguments instead of it being implicit using some sort of inflection.
Alternatively, you could only wrap the closure and use a dictionary of type Dictionary<String,Any>.
If you still need a workaround, here is one; usage looks like this:
var d : [String : AnyObject] = [:]
d["a"] = Blocks.voidBlockToId({ println("Doing something") })
d["b"] = "Some string"
d["c"] = Blocks.intBlockToId({ i in println("Called with integer: \(i)") })
Blocks.toIntBlock(d["c"])(1)
Blocks.toVoidBlock(d["a"])()
println(d["b"])
Output is:
Called with integer: 1
Doing something
Some string
The Blocks class is defined like this in Objective-C (with corresponding header and bridging header, I won't put those here):
typedef void(^VoidBlock)(void);
typedef void(^IntBlock)(int);
#implementation Blocks
+ (id) voidBlockToId: (VoidBlock) block { return block; }
+ (VoidBlock) toVoidBlock: (id) block { return (VoidBlock)block; }
+ (id) intBlockToId: (IntBlock) block { return block; }
+ (IntBlock) toIntBlock:(id)block { return (IntBlock)block; }
#end
You also need to add a new xyzBlockToId and toXyzBlock method for every new closure-type you want to use. It's pretty ugly, but it works.
There is another type, Any, that object, structs and primitives all conform to but functions do not. There is no general function type, but you can describe a function type as its arguments and return value like this:
Dictionary<String, (AnyObject) -> String>
Function Types
Could you use an NSMutableDictionary?
Alternatively, this seemed to work for me using your example:
1> import Foundation
2> var myDict: [String: (NSObject) -> String] = ["Key":{(value:NSObject) -> String in return value.description}]
myDict: [String : (NSObject) -> String] = {
[0] = {
key = "Key"
value =
}
}
3> myDict["Key"]!("Testing")
$R2: String = "Testing"
Hmm, maybe this Swift-Code doesn't really help, because you want to have heterogenous dictionaries.
It's also not possible to put closures into an NSDictionary, it seems (as a closure does not conform to AnyObject).
You could also roll your own higher type using an enum. You need the dictionary values to be either strings or functions which return strings, so define a type to represent that:
enum MyDictVal {
case ValString(String)
case ValFunc(AnyObject -> String)
}
Then, you can put it in a dictionary:
let d: Dictionary<String, MyDictVal> = [
"a": .ValString("a")
, "b": .ValFunc({ (value) in value.description })
]
Then you'll need to process the dictionary values using pattern matching:
switch d["b"] {
case .ValString(let s):
...
case .ValFunc(let f):
...
}
A more "generic" solution which should work with Any object, but shown with closures and function references. Drop it into a playground and try it out!
// Wrapper for sticking non-objects in NSDictionary instances
class ObjectWrapper {
let value: T
init(_ value: T) {
self.value = value
}
}
// convenience to downcast `as! ObjectWrapper` and return its value
func getValueFromObjectWrapper(a: AnyObject) -> T {
return (a as! ObjectWrapper).value
}
func wrappedObjectsInDictionary() -> NSDictionary {
var dict = NSMutableDictionary()
let appendToFoo: (String) -> String = NSString.stringByAppendingString("foo")
let firstChar: (String) -> Character = { $0[$0.startIndex] }
dict.setObject(ObjectWrapper(firstChar), forKey: "stringToChar")
dict.setObject(ObjectWrapper(appendToFoo), forKey: "stringTransformer")
return dict.copy() as! NSDictionary
}
let dict = wrappedObjectsInDictionary()
let appendToFoo: (String) -> String = getValueFromObjectWrapper(dict["stringTransformer"]!)
let strToChar: (String) -> Character = getValueFromObjectWrapper(dict["stringToChar"]!)
appendToFoo("bar") // "foobar"
strToChar("bar") // "b"

Resources