Subscribe now

Playgrounds & Built-in Types [11.08.2016]

Playgrounds

Let's get started by creating a playground.

On a Mac open Xcode; we'll use Xcode 8, which has Swift 3 support built in. Go to the File menu, and select New, then Playground... You’ll need to name it, and pick a platform. For our examples, it doesn’t matter which platform you choose, but iOS is the most popular platform. Finally, save the playground, and then we're ready to go.

The playground came with some code already in place.

Before you delete it, let’s take a look at that last line, var str = "Hello, playground". In the grayer area to the right, you’ll see the contents of the variable called str, and the playground will update these each time the variable changes.

Let's delete just the one line of code that begins with import. The playground automatically re-evaluates, and we still see the contents of the string in the sidebar. Playgrounds were specifically designed to make learning Swift easy, without concerns of a larger application in place. We didn't need to import any modules to make this happen.

Now, delete everything in the playground, and type the following:

print("Hello, debug area!")

While you do see the text show up in the sidebar, the print function sends text to the debug area. Click the button in the lower-left-hand corner of the playground window to see it.

The important distinction is the debug area will show all the text sent to the print global function, while the sidebar will only give a summary of each variable at its point in the code. Sometimes, the sidebar will be all you need. When it comes to debugging more complex behavior, you'll want the debug area as well.

While we're down here, let's talk about that blue button. It's the evaluate button. If we hold down the mouse, we can choose to only evaluate manually, when the button is clicked, or to let the playground re-evaluate for us. Most of our code examples will be simple enough that live reevaluation is fine. Depending on the machine, we may decide to run manually.

Built-in Types

Type this into the playground:

var aBoolean:Bool = true

This line of code creates a Boolean variable. We start with the keyword var, next comes the name of the variable. All variable names in Swift should be lower-camel-cased.

Next comes the type specification, the colon followed by the type name. All type names in Swift, both built-in types and user-defined types, should be upper-camel-cased.

Next comes the initial value, which is introduced with an = and followed by the value, true.

Type Inference

You may have read that Swift has type inference, so we don't need to write the type. That's true in many circumstances, like this. Let's remove the type

var aBoolean = true

This is fine, as far as it goes. But let's consider that I forgot that aBoolean was supposed to be a Bool, and not an integer.

var aBoolean = 1

This is also fine, until I try to use the integer as if it were a Bool. Let's put the type back in.

var aBoolean:Bool = 1  //error

Notice that the compiler now tells me about the error. This is great! Swift is a much safer language than C or Obj-C, largely due to its type system. If I had a function which returned a more complicated value than just a Bool, I might get confused or forget what exact type it is. The compiler goes along with me checking as I write, so I find including the types names in places where they can be inferred helps me. It also helps me read the code later on, when, again I forget which types it was.

You may be thinking, yeah, but it's so much typing that I don't have to do. Ok, sure, but type inference slows down Swift compared to compiling C or Obj-C, and including explicit types can speed it up. You'll be compiling a lot more than you're writing. So for both these reasons, catching mistakes upfront and faster compiles, I always include explicit types names.

Integers

So how would I store an integer? Type this

var anInteger:Int = 14

Int is the type name for a signed, machine-sized integer. What if I wanted an unsigned integer? That's UInt.

var aWholeNumber:UInt = anInteger

Suddenly, there's this red stop sign in the gutter. What' gives? Click it and it tells you about the compile-time error. We can't just create an unsigned integer with an Int like we could in some other languages. We'll need to convert it explicitly. Change the unsigned line to this:

varvar aWholeNumber:UInt = UInt(anInteger)

Now the compiler is happy. We've used a converting initializer to make a UInt from an Int. There are 2 ways of creating something in Swift: The first are the literals we've been using. And this is the second: a type name followed by parentheses, which is an initializer, or init method for short. We'll talk more about init methods another week.

There's still a problem here. Change the literal value to -14.

Now we get a red stop sign and the text is foreboding. "Execution was interrupted, ..."? This is no compile-time error. This is a run-time error. Unlike compile errors which prevent me from distributing code that will crash, run-time errors are crashes. We want to avoid these; all of them. We'll cover how as we progress through the lessons.

For the moment, just notice that as you read Swift API's, you'll see a lot of Int where you might have expected UInt in another language. There are two reasons for this, not just to avoid unnecessary crashes, but also to reduce the impedance mismatch of converting from Int to UInt and possibly back again.

Fixed-Width Integers

So how would I create an integer of a fixed number of bits? As an example, a 1-byte integer? That's UInt8.

var aByte:UInt8 = 5

Swift provides fixed-width signed and unsigned integer types with 1, 2, 4 and 8-byte counts. They are named by the number of bits. So for 2-bytes, and signed, it would be Int16.

var aShortInt:Int16 = 1000

Summary

Today, we learned that playgrounds help us learn the Swift language without requiring a larger application in place. Our code is live-reevaluated, and variables are summarized in the sidebar. More detailed logs can be printed to the debug area.

We began learning about built-in types, like booleans and integer. Ultimately, most of our data models will be built using these fundamental built-in types, so it's important to learn them well.

We also learned the difference between a compile-time error and a run-time error. Catching more errors at compile-time instead of run-time is a benefit of Swift, so as the course progresses, we'll point out how to take advantage of the compiler's checks.

Type safety, even between signed and unsigned integers? Now that's Swift!