Chapters

Hide chapters

macOS Apprentice

First Edition · macOS 13 · Swift 5.7 · Xcode 14.2

Section II: Building With SwiftUI

Section 2: 6 chapters
Show chapters Hide chapters

Section III: Building With AppKit

Section 3: 6 chapters
Show chapters Hide chapters

3. Using Swift in the Command Line
Written by Sarah Reichelt

Heads up... You’re accessing parts of this content for free, with some sections shown as scrambled text.

Heads up... You’re accessing parts of this content for free, with some sections shown as scrambled text.

Unlock our entire catalogue of books and courses, with a Kodeco Personal Plan.

Unlock now

In Chapter 1, “Introducing Xcode”, you installed Xcode and saw how to create a Mac app from the standard template. In Chapter 2, “Beginning Swift”, you turned your back on Xcode and ran Swift in the Terminal app. You learned about data types, variables, constants and collections.

In this chapter, you’ll return to Xcode, but not with the style of app you made in Chapter 1. This time, you’ll create a command line tool. This is an app without a graphical user interface that runs in Terminal.

When you ran the Swift REPL in Terminal, you executed a lot of single line Swift commands, but some Swift blocks need more than one line. It’s easier to edit and follow these in Xcode.

If you’re already familiar with conditionals, loops, functions and optionals in Swift, work through the first section of this chapter to learn about command line apps, and then you can skip ahead to the next chapter.

Creating the App

Start Xcode like you did in Chapter 1. If you see the “Welcome to Xcode” window, click Create a new Xcode project. If you don’t see that window, go to File ▸ New ▸ Project…. Either method gets you to the template chooser.

This time, select macOS ▸ Command Line Tool:

Selecting the Command Line Tool template.
Selecting the Command Line Tool template.

Click Next and give your new project the name swifty. Command line tools are traditionally named all in lowercase and with no spaces.

Leave Team set to None and enter your own organization identifier as you did in Chapter 1. Make sure the language is set to Swift, or this app won’t be very swifty. :]

Configuring your app.
Configuring your app.

Then click Next and decide where to save it.

If you make a folder in your user folder called Developer it automatically gets a cool hammer icon, so that’s always a good place to save your Xcode projects.

Running the App

When the app opens in Xcode, you’ll see that it only has one file: main.swift. This is a special file name and indicates the file that gets executed when the app runs. Open main.swift. First it imports the Foundation library, which is a basic library for any app, but isn’t necessary for any code you run from this chapter.

Running the app in Xcode.
Tuqcalv txu iyc eh Kfexa.

print("Hello Swift")
Edited output
Enesub oevmux

Hide the variables view.
Laqi ghe vaboadseq deug.

Using the Terminal App

Now you know how to run your command line tool from inside Xcode, but command line tools are normally run from Terminal.

Finding the built executable.
Sebdenf zha feuhr iputopovji.

./swifty
Running the swifty command.
Coqrapd yqi kxupyw yiyzuwt.

Terminal Paths

When you ran cd or swift repl in Terminal, you didn’t have to prefix the command with ./ so why did you have to do that here?

Making Decisions

One of the fundamentals of computer programming is having your code make decisions based on supplied information. In Swift, the most common way of doing this is with the if statement.

// 1
if true {
  // 2
  print("This is true")
}
if true
ud qxui

// 1
var userIsLoggedIn = true

// 2
if userIsLoggedIn {
  print("Welcome")
}
if with a Boolean variable
ay wirp i Zeiyooc dejuiqse

If … Else

So far so good, but what about printing a different message if the user isn’t logged in? For that, you need to add an else.

if userIsLoggedIn {
  print("Welcome")
} else {
  print("Please log in")
}
if ... else
il ... ohro

Evaluating Conditions

The condition doesn’t have to be a Boolean variable. It can be any code that evaluates to give a Boolean result.

// 1
var name = "Bob"

// 2
if name.count < 4 {
  // 3
  print("\(name) is a very short name")
} else {
  // 4
  print("Good name.")
}
A short name
A zjerq xufu

A longer name
A jowtor lega

Comparison Operators

To create a Boolean result, you used a comparison operator — in this case, the less than operator. As you’d expect from the name, comparison operators compare the value on the left to the value on the right and return either true or false.

If … Else If … Else

There’s an even more expanded way to use if to do even more checks. Add this block to your code in main.swift:

// 1
var score = 70

// 2
if score >= 100 {
  print("You've won")
// 3
} else if score > 80 {
  print("Nearly there...")
// 4
} else {
  print("Keep going")
}
if ... else if ... else
ot ... eflu of ... uzci

Switching

A switch statement is a different method for doing comparisons. You switch on a particular value and state what happens at each stage.

// 1
var grade = "B"

// 2
switch grade {
// 3
case "A":
  print("Top of the class!")
case "B":
  print("Excellent work.")
case "C":
  print("Solid effort.")
case "D":
  print("Try harder next time.")
// 4
default:
  print("More effort needed.")
}
switch
knocpj

Looping

One thing that computers are great at is repeating the same actions over and over. Swift gives us several different ways to loop repetitively.

// 1
for number in 1 ... 5 {
  // 2
  print(number)
}
A for loop with a closed range.
U deq coig qayy o fbisiv mucse.

A for loop with a half-open range.
U dog quel cuzn e dezz-utab jitju.

While Loops

There are two forms of the while loop, with an important distinction.

// 1
var counter = 0

// 2
while counter < 5 {
  // 3
  print("Counter: \(counter)")
  // 4
  counter += 1
// 5
}
A while loop
O ktexe xiay

Repeat While Loops

That covers the first way to use a while loop, but there’s a second form called a repeat … while loop.

// 1
var counter = 0

// 2
repeat {
  print("Counter: \(counter)")
  // 3
  counter += 1
// 4
} while counter < 5
A repeat ... while loop
O geziap ... gfehe seuw

Looping Through Arrays

So far, you’ve looped using numbers, but in the last chapter, you learned about arrays. Swift provides a convenient way to loop through them too.

 let toys = ["Andy", "Bo-peep", "Buzz", "Jessie", "Rex"]
Xcode's auto-complete
Qdive'g iiqi-mesltiqe

let toys = ["Andy", "Bo-peep", "Buzz", "Jessie", "Rex"]
for toy in toys {
  print(toy)
}
Looping through an array.
Luepinb bvtaigk ek odlix.

Writing Functions

All the code you’ve written so far executed immediately. Functions are blocks of code that only run when you call them. This makes them useful for code that you may need to run multiple times in your app.

func showVersion() {
  print("swifty - version 1.0")
}
showVersion()
Running your first function.
Pamjoyf coul didyb jaxwkuow.

Providing Input

You use the space between the parentheses to tell the function what arguments or parameters to expect.

// 1
func showVersion(versionNumber: Double) {
  print("swifty - version \(versionNumber)")
}

// 2
showVersion(versionNumber: 1.2)
A function with an argument.
O sidhqeab sust ut ezvedoxp.

Receiving Output

You’ve used two functions now: the first one took no input, the second one received an argument. The remaining piece in this sequence is to get information back from a function.

// 1
func getVersion() -> Double {
  // 2
  return 1.3
}

// 3
let versionNumber = getVersion()
print("Version \(versionNumber)")
A function that returns a value.
U fixxyuaq sqot cixifkd u getau.

Combining Inputs and Outputs

The final step is to write a function that does both: takes input and returns output.

// 1
func areaOfCircle(radius: Double) -> Double {
  // 2
  let area = Double.pi * radius * radius
  // 3
  return area
}

// 4
let area = areaOfCircle(radius: 6)
print(area)
A function with input and output.
U qidvzoiv piqr esnez igr oohzep.

Optionals

Now to the last topic in this chapter — optionals. You encountered optionals briefly in the last chapter, but it’s time to learn about them in more depth.

// 1
var mightBeNumber: Int?

// 2
print(mightBeNumber)

// 3
mightBeNumber = 3

print(mightBeNumber)
Printing an optional.
Zwuftedk uj ovxoopuz.

Unwrapping

Replace your code with this new version:

// 1
var mightBeNumber: Int? = 3

// 2
if let mightBeNumber {
  // 3
  print(mightBeNumber)
} else {
  // 4
  print("mightBeNumber is nil")
}
Unwrapping an optional.
Ahgjaykodc ud elcueyom.

Force Unwrapping

Before leaving this topic, there are two more points to cover. The first is force unwrapping.

var forcedString: String? = "This really is a string."
print(forcedString!)

Guard Let

The other point is a form of unwrapping that’s most often used in functions, called guard let which is the inverse of if let. Where if let says what to do if there is a value, guard let runs when there is not a value.

func handlingOptionals(name: String?, age: Int?) {
  if let name {
    if let age {
      print("All input data is valid: \(name) & \(age)")
    } else {
      print("age is not an Int")
    }
  } else {
    print("name is not a string")
  }
}
func handlingOptionals(name: String?, age: Int?) {
  guard let name else {
    print("name is not a string")
    return
  }

  guard let age else {
    print("age is not an Int")
    return
  }

  print("All input data is valid: \(name) & \(age)")
}
func handlingOptionals(name: String?, age: Int?) {
  guard let name, let age else {
    print("One of the arguments is not valid")
    return
  }

  print("All input data is valid: \(name) & \(age)")
}
guard let
xaupx xan

Key Points

  • A command line tool is an app without a graphical interface that runs in Xcode or in Terminal.
  • Swift can make decisions using if or switch. If you have more than three possibilities, use a switch.
  • Loops use for or while to step through data.
  • Functions allow you to create reusable chunks of code that can take input and provide output.
  • Optional variables are variables that can be nil, but are still strongly typed.

Where to Go From Here

In the downloaded materials for this chapter, in projects ▸ final there’s an Xcode project containing the code used in this chapter.

Have a technical question? Want to report a bug? You can ask questions and report bugs to the book authors in our official book forum here.
© 2024 Kodeco Inc.

You’re accessing parts of this content for free, with some sections shown as scrambled text. Unlock our entire catalogue of books and courses, with a Kodeco Personal Plan.

Unlock now