Swift Optionals Quick Reference

Swift Optionals Quick Reference for Newbies by Santiapps.com
Swift Optionals Quick Reference for Newbies by Santiapps.com
Swift Optionals Quick Reference for Newbies by Santiapps.com

Optionals confuse me so I wrote this post and hope it can be of some help.

OPTIONALS

Takeaway #1: Optionals are used to declare a variable but are not assigned a value at start

Takeaway #2: Optionals contain a Some or None value, they DONT contain a String or Array or whatever else.

Takeaway #3: Therefore we MUST unwrap the value of an Optional to see what the prize is 🙂 In other words, to access its value!

Takeaway #4: DECLARATION OPTIONS

A) Using the following syntax: var someVar? – You will mostly use this…

B) Using “var someVar!” <Implicitly unwrapped> – Unfortunately UIKit & other Apple frameworks will use a lot of these…

… NEED TO EXPLORE THE DIFFERENCE BETWEEN ? and ! declarations…

Turns out you can declare a variable as an implicitly unwrapped optional if you know it will, at some point, be non-nil.  So for example, in this SO post (http://stackoverflow.com/questions/24006975/why-create-implicitly-unwrapped-optionals) they talk about have viewDidLoad in a view controller call a setter upon load:

var screenSize: CGSize?

override func viewDidLoad() {

super.viewDidLoad()

screenSize = view.frame.size

}

We know that screenSize will be filled because viewDidLoad WILL be called.  Then later we do:

@IBAction printSize(sender: UIButton) {

println(“Screen size is: \(screenSize!)”)

}

We know screenSize will have a value if its ever called.  So we can instead declare it as an implicitly unwrapped optional with a ! instead of a ? in the initial var declaration.  But don’t sweat this so much right now.

Takeaway #5: ACCESS (UNWRAPPING) OPTIONS 

Takeaway #6: Method 1: Traditional (Risky): if var != nil and then access it inside the if block.

if yourOptionalTypeOrOptionalReturningFunction != nil {

doSomethingWith(tempOptional!) || setSomeValue = tempOptional!

}

But to access it you have to unwrap the present 🙂  To do this you use the bang operator !  Whenever you use the ! you are ‘force unwrapping’ a variable, which means it will open it no matter what.  If nil is in there…KABOOM!  Bye bye Moose & Squirrel!  So you better have checked before hand.

Takeaway #7: Method 2: Optional Binding (aka:”if-let nil check”) (Safer): This means you use:

if let tempOptional = yourOptionalTypeOrOptionalReturningFunction {

doSomethingWith(tempOptional) || setSomeValue = tempOptional

}

This is more safe because it checks first or peeks in the box so to speak.  Thus you can use the variable without unwrapping.

< If you remove default value from a ? and have a ! to access it in code, your code will fail if-check will go to else.>

Takeaway #7: Method 3: Implicitly Unwrap: Uses ! operator (assumes var contains some value). But remember from Method 1, if nil, KABOOM!!!!!!

<If you remove default value from a ? and have a ! to access it in code, you get runtime crash = error = “can’t unwrap optional.None”>

Takeaway #8: Optionals unwrapped using? – This one is still kinda confusing to me. Has to do with optional chaining and inline downcast syntax I believe.  It means that when you have many optionals.  Let’s assume you have a class with 2 optional variables, name? and price?  Let’s pretend you write a function that creates a new Stock() class object and must therefore set name & price variables for it.  We would first have to check if one is set and then the other:

if let someName = stock.name {

if let somePrice = stock.price {

//now we can do something with price…

}

}

This would get messy.  So we chain them into a single statement like so:

someVariableWeWantToSet = stockName?.stockPrice

Takeaway #10: Many ObjC framework objects are optionals? and many are implicitly unwrapped! when passed into functions because they will start out as nil (UILabels, MKAnnotationViews or MKPolylines) but we know they will eventually get filled in because that’s why we put them there in the first place:

MKAnnotationView!

MKAnnotation!

UIControl!

MKPinAnnotationView!

MKMapView!

Takeaway #11: When we have something like an MKAnnotation! is received in a function as annotation. If we wish to use its super class properties, we must be inline downcast to while if-let checking. Once inside we can implicitly (force) unwrap MKPinAnnotationView! because we know since the annotation exists, it will have a view. For example, in this method:

func mapView(mapView: MKMapView!, rendererForOverlay overlay: MKOverlay!) -> MKOverlayRenderer! {

if let polylineOverlay = overlay as? MKPolyline {

let renderer = MKPolylineRenderer(polyline: polylineOverlay) renderer.strokeColor = UIColor.blueColor()

return renderer

}

return nil

}

We can interpret that funky as? as follows: “If when I get the variable overlay and unwrap it, it downcasts successfully to a MKPolyline && I get a value (not-nil) then put it into polylineOverlay & continue…” Hope this helps…

Why, oh Why, did Apple take away ARC just to give us Optionals!?

I’m having trouble understanding optionals so here is a shot at explaining them. 🙂

var thisIsAnInt: Int

Simple, this is an Int variable declaration.

var couldBeAnInt: Int?

This on the other hand is an optional variable declaration.

This optional declaration doesn’t mean: “this is an int, which is optional”.

It reads more like: This is an OPTIONAL variable.  It’s a type of variable in and of itself.  Its NOT NECESSARILY an Int.  It just may or may NOT contain an Int”.

Woah!

Ok so what is it for and when do you use it.  Well that part seems simple enough:

If that variable can or could or may be nil at some point, it’s an optional.

If the variable will always have a value, it will never be nil, its NOT an optional.

Don’t be misled by this simplicity.  Some variables can start out as nil and receive a value at some point.  What then?

Well it turns out there is a sort of table, if you will:

  1. Can NEVER be nil (or if it IS, its a bug) = non-optional variable….you know, the regular kind
  2. Starts out nil but NEVER ends up nil after init (or if it is, its a bug) = implicitly unwrapped optional
  3. Nil value has meaning and is expected (if it is, its NOT a bug) = optional

Yeah, thanks for confusing me :S

Here is another way around it:

var perhapsInt: Int? //this is perhaps an Int
perhapsInt = 1 //here we assign it an int
if perhapsInt != nil { //now we check to see if its nil before using it
     let intString = String(perhapsInt!) //IF it isn't, then we can access it by using !
     println(intString)
}

you can also check for that in a different way:

var perhapsInt:Int?
perhapsInt = 1 
if let actualInt = perhapsInt {
     println(actualInt)
}

Here is the kicker:

var perhapsInt: Int?
let definiteInt = perhapsInt ?? 2
println(definiteInt) // prints 2
perhapsInt = 3
let anotherInt = perhapsInt ?? 4
println (anotherInt) // prints 3

And it gets trickier what with ?? and variable != nil.  So let’s throw everything out the window and start anew.  Let’s define a function we might actually be interested in:

Assume we have an array of locations:

let errorCodes = ["100","200","300","400", "500"]
func findErrorCode (code : String, errorCodes: [String])-> String {
for tempCode in errorCodes {
     if ( tempCode == code) {
     return code
     }
}
return ""
}

This is a function we wrote to find a particular code inside an array of possible error codes.  We call it by passing it in a code and the array of possible codes.  If we pass it a code that is NOT in the array, let’s say “700”, then the “internal if” will not evaluate to true and we must return nil.  We must return nil because otherwise, because the function is meant to return a String (the name of the matched code) && that “if block” didn’t hold true, you get a compiler error because we are not being exhaustive.  This means, if we pass the function a value that IS in the array, great, we will get a ‘return code’.  However, if we pass it a value that is NOT in the array, the function would not be returning anything.  So we NEED to return something for it to work.

We could return an emply value but consider the following.  Let’s say we wish to display that code returned in the console, via println (or plot it on a map of servers for example).  The point being that we need to do something with the returned code:

if findCode("700", errorCodes) {
	plotOnMap()
}

So how do we account for such a possibility?  We need to define the return value of the function findCode as an optional.  To do this we add this to the variable “?”.  Here is what the function would look like:

func findCode (code : String, errorCodes: [String])-> String? {
for tempCode in errorCodes {
     if ( tempCode == code) {
          return code
     }
}
return nil
}

Now we can actually return a String value, maybe, or we could be returning an Optional value.

Great, now let’s asume the plot function looks like this:

func plotOnMap (code: Int) -> () {
     println("This line of code magically plots the code on a server map :)")
}

Ok so now we can say

let receiver = findCode("200",errorCodes)
if receiver {
	plotOnMap(receiver);
}

The issue is that the value returned by findCode, is Optional.  So the value of receiver will be optional.

This is what is called “implicitly defined optional“.  We have implicitly defined receiver to be an optional because the return of the function is an optional itself.

We also have another issue, plotOnMap() takes an Int, not a String.  So we have actually defined receiver as:

let receiver: String? = findCode("400",errorCodes) // inferred type String?

Notice we have defined it as String?, not String.  This means receiver can hold a String or a nil, because its being defined as an Optional type, not a String type.

So what can we do?  We can ask it for a value only if it HAS one:

let receiver = findCode("400",errorCodes) 
if receiver {
	plotOnMap(receiver!) // We use of the ! operator to unwrap the value to String
}

This would indeed fix the problem.  You have solved the possibility of an optional in a function you wrote yourself.  But there is always the other case, values returned by functions you DIDNT write!  Ugh!  Remember I mentioned that our plotOnMap() takes an Int, and not a String?  And we are in fact unwrapping an implicitly defined variable (called receiver) into a String (cause that’s what the function returns?  Well we need to convert it into an int, which is simple in Swift, just say string.toInt().  This means we have to do this:

if let receiver = findCode("400",errorCodes) {
	plotOnMap(receiver.toInt())
}

But if you jump to definition on toInt(), you will notice that it also returns an optional.  So we would need to do something more convoluted:

if let receiver = findCode("400",errorCodes) {
	if let receiverErrorCode = receiver.toInt() {
		plotOnMap(receiverErrorCode)
	}
}

which is quite confusing.  So there is a Swift syntax which let’s you condense this into:

if let receiverErrorCode = findCode("400",errorCodes)?.toInt() {
	plotOnMap(receiverErrorCode)
}

It would be prudent just to add an else to the if to be safe 🙂

iOS : Swift : Blocks = Closures

Closure on closures
Closure on closures

I’ve never really liked blocks in ObjC.

When Swift came out it made things more complicated for me because I’ve never really liked C either.

Finally when I had to deal with closures in Swift, well that’s just gonna piss a lot of people off!

After a few days reviewing tons of material online, and I mean TONS!  I came to understand this:

The only C-like exposure I had prior to ObjC was a little PHP.  So that allows me to understand a function, which is the equivalent of a method in ObjC:

DECLARING

func sayHello( ) {

     println(“Hello World”)

}

CALLING

sayHello( )

RESULT

Hello World

Even if you didn’t have any exposure to C or PHP or some other “not-so-friendly” language as ObjC, you can surely understand that

  1. The function is called sayHello
  2. That it takes no input-parameters because the ( ) is empty
  3. That it has no return type because it returns nothing since its missing the keyword “return” inside of it 🙂
  4. And that all it does, instead of returning a value, is print out Hello World

Just to clarify, let’s look at a function with a return value:

DECLARING

func sayHello () -> String {

    var result = “Hello World”

    return result

}

CALLING

var whoAreYou = sayHello()

RESULT (value of whoAreYou)

Hello World

As you can see here, we actually return a value from this function, which we can assign to a variable.  I had to assign it to a variable so that it made sense to actually return a value from a function.  

So we added an output-value to an otherwise plain vanilla function.  Now lets go for the next kind of function, plain + output + input:

DECLARING

func sayHello (friendOne:String) -> String {

    println(“Hi \(friendOne)”)

    var result = “Hello, ” + friendOne

    return result

}

CALLING

var whoAreYou = sayHello(“Marcio”)

RESULT (value of whoAreYou)

Hello, Marcio

Great!  So you’ve got functions covered:

  • Plain void functions
  • Returning output-value functions
  • Input-Paramter, returning output-value functions

CLOSURES (or blocks from ObjC)

There really is no simple way to explain it in a few words.  But the first thing that stands out from a closure or block, is that IT IS a function, yes!  But it can be passed around like a variable.  So let’s take a look:

var someVariable: String

There, we just declared a variable of type string.  Let’s declare another variable:

var someOtherVariable: ( ) -> ( ) = { }

There, we have just declared another variable, of type…? :s

Simply combine the concepts:

variable = function

And we know that a function is:

function = functionName (input-parameter) -> (Output-value) {some code}

So now say:

variable = function = functionName (input-parameter) -> (Output-value) {some code}

Now drop the middle “function” 🙂

variable = functionName (input-parameter) -> (Output-value) {some code}

If you don’t want the function to have a name, because you are assigning it to a variable anyway, so you can just call it by calling the variable:

variable = (input-parameter) -> (Output-value) {some code}

Hey, that looks a lot like what we had above:

var someOtherVariable: ( ) -> ( ) = { }

Cool!  So what does it all mean Basil?

The important thing is that you will use closures in Swift.  I was working with Parse SDK the other day and I ran into this in Xcode:

Get closure on Closures
Get closure on Closures

This is the first stage of Autocomplete which you may already be familiar with.  It’s telling you this:

Void saveInBackgroundWithBlock(block: PFBooleanResultBlock!(Bool, NSError!) -> Void)

You already know what this means, its just a function/method that takes a block as a parameter.  

This function returns Void, according to the left Void in that line.  

Let’s say that the method is called saveInBackgroundWithBlock ( X ) and it takes 1 parameter, X, where X is a block.

The block is defined as a variable “block:” and its called PFBooleanResultBlock!

It has 2 output-values Bool & NSError.

Now you know how to fill it in.  But wait, there’s more…if you call in the next 15 minutes 🙂

But seriously, Xcode now has something new.  Check it out!  To select that method in the image above, you hit Enter.  This spits out the method signature in the Editor window and expects you to fill in the rest…THE NERVE!  Luckily, you can hit Enter again while that blue selection is highlighting the block and that will give you this:

tah dah!

Get closure on Closures
Get closure on Closures

Now that’s better!  This is Xcode’s new second stage Autocomplete.  Its telling us that the block is defined by { } and it takes 2 input-parameters and returns a Void.  That new “in” keyword serves to separate the return (which is in this case, Void) from the actual code block which follows.

So you can call closures like so:

object.saveInBackgroundWithBlock {succeeded, error in

//some code

}

OR

object.saveInBackgroundWithBlock { (succeeded, error) -> Void in

//some code

}

 OR

object.saveInBackgroundWithBlock( { (succeeded:Bool, error:NSError!) in

//some code

})

OR

object.saveInBackground( { (succeeded:Bool, error:NSError! ) -> Void in } )

OR you can assign it:

var someVar: () -> () = {              

println(“Hello World”)

}

Enjoy!

 

EDIT: In brief:

How to write or declare closures:

{ (succeeded: Bool, error: NSError?) -> Void in /* code */ }
{ (succeeded: Bool, error: NSError?) in /* code */ }
{ (succeeded, error) in /* code */ }
{ succeeded, error in /* code */ }
{ /* code using $0 for succeeded and $1 for error */ }

How to pass a closure:

object.saveInBackgroundWithBlock({ /* closure */ })
object.saveInBackgroundWithBlock() { /* closure */ }   // Only if closure is last arg
object.saveInBackgroundWithBlock { /* closure */ }     // Only if closure is only arg