Swift

An Introduction to Swift Optionals

Swift OptionalsIf you are anything like me, the concept of Swift Optionals can be a little confusing. At first blush, it seems fine, but then the way that you have to work with them can leave you scratching your head.

The idea is simple. Swift Optionals are essentially nullable/nillable types from other languages. Obviously, reference types can always be null or nil (depending on the language), but value types cannot. In most (if not all) languages that I am familiar with, you cannot have a null integer or a null boolean. You used to have to be left with creating some logic or understanding that if an Id column was 0 or -1, that meant that it had never been set. Or, you had to never fully rely on a boolean’s false value. It could mean no one had ever set some conditional, or it could mean they had “chosen” and they had chosen “no” or “off”.

In C#, they implemented nullable types to solve this problem. I have an example below of using nullable types. You’ll note that you can actually declare them two ways. Like many things in modern languages, there is the “defined” way and the “shorthand” way. There are a few things I want you to note. First, before you use it, you should check and see if it has a value by consulting its “HasValue” property. But, how could you do that if it is null? It isn’t actually null. The nullable type is actually a container. You are asking the container if anything is inside. The other thing to note is that when I want to use it, .Net infers the call to id.Value for instance. I left it as implicit for id and explicit for otherId so you can see the difference.

Nullable<Int32> id = null;
int? otherId = 7; // int? is just "syntatic sugar" for Nullable<Int32>

if (id.HasValue)
{
	Console.WriteLine("The id's value is {0}", id);
}
else
{
	Console.WriteLine("Id has a null value");
}

// We could also be more concise, but maybe less readable
Console.WriteLine(otherId.HasValue ? string.Format("Other Id's value is {0}", otherId.Value) : "Other Id has a null value");

If I had called .Value on id while it was set to null, I would have gotten an error that said “Nullable object must have a value”. That’s why you must check.

So, how does this relate to Swift? The syntax is actually very similar to C#’s. I use the question mark to denote that I’ve declared an optional variable. However, if I try to use it like C# and just print it out, I get something that can be confusing. Take a look at this code:

var id: Int? = 7

print(id)

Here is what is output, “Optional(7)”. Unlike C#, it didn’t just auto-unwrap and show 7. It is showing you visibly that that 7 is “wrapped inside an Optional”. That is because – like C# – the ? is “syntactic sugar”. What you are really declaring is this:

var id: Optional<Int> = Optional<Int>(7)

print(id)

Now it is really no wonder why we see “Optional(7)” as the output. Swift is literally just giving us back what is there. What if you wanted to unwrap it, then? To unwrap it, you use the ! symbol, like this:

var id: Int? = 7

print(id!)

That will actually output “7” to your console. But, what will this code do?

var id: Int? = nil

print(id!)

If I try to force unwrap a nil value, I get this error, “fatal error: unexpectedly found nil while unwrapping an Optional value”. Bad news. One way that you often see this dealt with is like this:

var id: Int? = nil

if let unwrappedId = id {
    print("Id unwrapped is \(unwrappedId)")
}
else {
    print("That was nil")
}

In our case, this code prints “That was nil”. If you change the first line to var id: Int? = 7, it will now output “Id unwrapped is 7”. But… why? This syntax makes use of a few things. First, nil evaluates as false in Swift. Secondly, the “if let” is special syntax to Swift. The variable is only unwrapped in this way in an “if let” scenario. And “if let” only works if you have an Optional being assigned.

For instance, I can’t do either of these:

if let seven = 7 {
    print ("Worked")
}

var id: Int = 8

if let eight = id {
    print("Bingo")
}

The compiler errors on both items say, “initializer for conditional binding must have Optional type, not ‘Int'”.

So, “if let” is what you have to work with if you want to check variables and do something different in execution if they are not there. However, you have other options. What if you are handed an Optional, but you just want to work with a “sensible default”? You can stick with “if let” if that makes sense to you. That would look like this:

var incomingVariable: Int? = nil

var myInternalVariable:Int

if let unwrappedIncomingVariable = incomingVariable {
    myInternalVariable = unwrappedIncomingVariable
}
else {
    myInternalVariable = 0
}

print(myInternalVariable)

Another option is to skip the “else” entirely and just preset your variable to what the default should be. If the Optional variable has a value, it will just be overwritten. The previous code and this code both print out “0” to the console.

var incomingVariable: Int? = nil

var myInternalVariable:Int = 0

if let unwrappedIncomingVariable = incomingVariable {
    myInternalVariable = unwrappedIncomingVariable
}

print(myInternalVariable)

What if you would like to be a little more concise? You do have the option of using the Swift coalesce operator, ??. That would reduce the previous example to something like this:

var incomingVariable: Int? = nil

var myInternalVariable:Int = incomingVariable ?? 0

print(myInternalVariable)

That’s all there is to Optionals at their core. In another post, I’ll revisit Optionals and see how you can use them in iOS applications to deal with controls and casts. If you have any questions, let me know.

Podcasts

Podcast Episode 40 – whoami, an identity crisis

In this episode, I come back from my almost seven month hiatus to wonder about what this podcast should be and if I am putting out the kind of content that my audience and the audience at large is looking to hear. I talk about my original plans for the show, what I see in the podcasting space as a whole, and where I could go in the future. In the end, though, I am looking for feedback.

Leave a comment or tweet me @PeteOnSoftware and let me know. Should I:

  • Keep it up
  • Change it up (become more narrowly focused… if so, on what)
  • Give it up

Links Mentioned in this Show:

Gimlet Media

You can also subscribe to the podcast at any of these places:
iTunes Link RSS Feed

Thanks to all the people who listen, and a special thanks to those who have rated me. I really appreciate it.

The episodes have been archived. Click Here to see the archive page.

Swift

Swift Extension Methods

I’m doing this code in the latest version of Xcode that is available as of this writing, Xcode 7 Beta 6. It does not work with Xcode 6 at all, because some of the features are only part of Swift 2.
Extension CordExtension methods are a language feature that allows you to add behavior to a class (“extend” that class’ functionality, if you will).

In .Net, extension methods are merely syntactic sugar. I previously talked about them here and here. I go into more detail in the links, but basically extension methods are implemented as new methods that take the “extended object” as a parameter. You might declare one something like this:

public static class StringExtensions
{
    public static bool StartsWithACapitalLetter(this string input)
    {
        return !string.IsNullOrEmpty(input) && Char.IsUpper(input[0]);
    }
}

Then, when I call “Pete”.StartsWithACapitalLetter() it returns true and “pete”.StartsWithACapitalLetter() returns false.

So, that’s .Net. What about Swift? In Swift, similar functionality can be achieved this way.

extension String {
    var StartsWithACapitalLetter:Bool {
        if (self.isEmpty) { return false }
        let firstCharacter = String(self.characters.first!)
        return firstCharacter == firstCharacter.uppercaseString
    }
}

As it stands, if I call “Pete”.StartsWithACapitalLetter I get true and “pete”.StartsWithACapitalLetter gives me false. Let’s break it down a little more.

The first thing you do is just use the Swift keyword extension in front of the name of the class you are extending. After that, you literally just “add code” to the class. In this case, I added a property (not a method) called StartsWithACapitalLetter that returns a boolean. Notice that within that method, I can use self just as if I had written this code inside of the original class itself.

That’s really all that there is to it.

Swift

Swift – Repeat Keyword

RepeatIn the Swift Programming Language – like all programming languages – we are given a lot of ways to control the flow of the program. Back when Swift was first introduced, I wrote a post to talk about the ways that Swift offered to control program flow.

One of the ways that I covered in that post was the while keyword. Using a while statement will cause the program to evaluate a condition first before it would ever execute the block. Take this code for example:

var counter:Int = 0

while counter < 10 {
    print("counter is at \(counter)")
    counter++
}

This results in the output of:

counter is at 0
counter is at 1
counter is at 2
counter is at 3
counter is at 4
counter is at 5
counter is at 6
counter is at 7
counter is at 8
counter is at 9

However, if you ran the following code:

var counter:Int = 0

while counter > 0 {
    print("counter is at \(counter)")
    counter++
}

There is no output. Since counter is 0 and the while block only executes for positive values, nothing happens.

Let’s see how repeat is different. We’ll try the first example again.

var counter:Int = 0

repeat {
    print("counter is at \(counter)")
    counter++
} while counter < 10

This results in the same output of

counter is at 0
counter is at 1
counter is at 2
counter is at 3
counter is at 4
counter is at 5
counter is at 6
counter is at 7
counter is at 8
counter is at 9

But, the second example of

var counter:Int = 0

repeat {
    print("counter is at \(counter)")
    counter++
} while counter > 0

Results in the code running for ever and ever and ever. It only asked if the variable was greater than 0 after the first pass. Since by the time the code had exited the repeat block the value of counter was 1 (and therefore positive), we just kept going (I stopped it when the last few entries looked like this):

counter is at 10789
counter is at 10790
counter is at 10791
counter is at 10792
counter is at 10793
counter is at 10794
counter is at 10795
counter is at 10796
counter is at 10797
counter is at 10798
counter is at 10799

You might be saying to yourself, but Pete.. this sounds exactly like a do-while loop vs a while loop. Well, you’d be 100% correct. Even according to the Swift documentation, “The repeat-while loop in Swift is analogous to a do-while loop in other languages”. C’est la vie!

Business of Software

Podcast Episode 39 – Warren Buffett’s 25 and 5 Rule w/ bonus Amazon Underground Discussion

Warren Buffett, By USA International Trade Administration (https://www.youtube.com/watch?v=GLKDFhCjaY4) [Public domain], via Wikimedia CommonsToday, I heard about Warren Buffett’s “Two List Strategy”, also known as the “25 and 5 Rule”. I don’t know if the story is apocryphal or real, but I think the lesson is just as valid. When I got to my picks of the week, the first one went the normal way. But then I started talking about Amazon Underground and apparently I hit a hot button with myself. I ended up talking about Amazon Underground for about as long as Warren Buffett’s strategy. We go where the muse goes 😉


Links Mentioned in this Show:
Warren Buffett’s Two List Strategy
David Smith’s Twitter
Do Not Let Your Users See Spinners
Amazon Underground

You can also subscribe to the podcast at any of these places:
iTunes Link RSS Feed

Thanks to all the people who listen, and a special thanks to those who have rated me. I really appreciate it.

The episodes have been archived. Click Here to see the archive page.