iOS App Launch with UIKit Architecture
Swift Programming Basics
Your First Steps in Swift
Swift is the language used to build apps for all of Apple's platforms. It’s designed to be safe, fast, and easy to read and write. Let's start with the most basic building blocks: storing information.
In Swift, you store values in either a constant or a variable. If a value won't change, you use a constant. If it might change later, you use a variable. You declare constants with the let keyword and variables with var.
let score = 100 // This is a constant. Its value can't change.
var currentHealth = 95 // This is a variable. We can update it.
currentHealth = 80 // This is okay.
// score = 110 // This would cause an error!
Every variable and constant has a type, which tells Swift what kind of data it holds. Swift is smart and can often figure out the type on its own, a feature called type inference. But you can also be explicit if you want.
Here are a few fundamental data types:
- Int: For whole numbers, like -10, 0, and 42.
- Double: For numbers with a fractional component, like 3.14159 or -0.5.
- String: For text, like "Hello, world!".
- Bool: For true or false values, which are great for making decisions.
// Swift infers the types here
let playerName = "Alice" // String
let level = 5 // Int
let hasKey = false // Bool
// You can also be explicit with a colon
var mana: Double = 99.5
Making Decisions and Repeating Tasks
Storing data is useful, but the real power of programming comes from making decisions and performing actions based on that data. This is called control flow.
To run code only when a certain condition is true, you use if, else if, and else statements. It's like giving your program a choice.
let temperature = 75
if temperature > 80 {
print("It's hot outside!")
} else if temperature < 60 {
print("Better bring a jacket.")
} else {
print("It feels just right.")
}
When you need to repeat an action multiple times, you use a loop. The most common type is a for-in loop, which is perfect for running a block of code for each item in a collection, like an array of numbers or strings.
let groceryList = ["Apples", "Milk", "Bread"]
for item in groceryList {
print("I need to buy \(item).")
}
Packaging Your Code
As your programs grow, you'll find yourself writing the same lines of code over and over. Functions let you package up a piece of code, give it a name, and run it whenever you need it. This makes your code cleaner and easier to manage.
A function can take in data (called parameters) and can also return a value as its output.
// This function takes a name and returns a greeting
func greet(person: String) -> String {
let greeting = "Hello, " + person + "!"
return greeting
}
// Now we can call the function
print(greet(person: "Bob")) // Prints "Hello, Bob!"
Sometimes you need a small, unnamed chunk of code to pass into another function. These are called closures. They're like functions without a name. You'll see them used frequently in Swift, especially for tasks that should happen later, like when a network request finishes.
let names = ["Chris", "Alex", "Ewa", "Barry"]
// Use a closure to sort the names alphabetically
let sortedNames = names.sorted(by: { (s1: String, s2: String) -> Bool in
return s1 < s2
})
print(sortedNames) // Prints ["Alex", "Barry", "Chris", "Ewa"]
Building with Blueprints
Object-oriented programming (OOP) is a way of thinking about code by modeling real-world things. In Swift, one of the main ways to do this is with a class. A class is like a blueprint for creating objects. For example, you could have a Car blueprint that defines what all cars have (properties) and what they can do (methods).
Properties are the variables and constants that belong to the class, and methods are the functions that belong to it.
class Dog {
// A property
var name: String
// An initializer to set up a new instance
init(name: String) {
self.name = name
}
// A method
func bark() {
print("\(name) says: Woof!")
}
}
// Create an instance of the Dog class
let myDog = Dog(name: "Fido")
// Call its method
myDog.bark() // Prints "Fido says: Woof!"
Handling the Unexpected
Not everything in a program goes according to plan. A network connection might drop, a file might be missing, or a user might enter invalid input. Instead of letting your app crash, you can use error handling to manage these situations gracefully.
In Swift, you can create functions that can throw an error when something goes wrong. To call one of these functions, you use a special do-catch block. You try to run the code that might fail. If it throws an error, the catch block runs, and you can handle the problem there.
// An enum to represent possible errors
enum VendingMachineError: Error {
case invalidSelection
case insufficientFunds(coinsNeeded: Int)
}
// A function that can throw an error
func vend(item: String, coinsDeposited: Int) throws {
if item != "Chips" {
throw VendingMachineError.invalidSelection
}
if coinsDeposited < 5 {
throw VendingMachineError.insufficientFunds(coinsNeeded: 5 - coinsDeposited)
}
print("Dispensing Chips")
}
// Call the function in a do-catch block
do {
try vend(item: "Chips", coinsDeposited: 3)
} catch VendingMachineError.invalidSelection {
print("Invalid Selection.")
} catch VendingMachineError.insufficientFunds(let coinsNeeded) {
print("Insufficient funds. Please insert an additional \(coinsNeeded) coins.")
} catch {
print("An unknown error occurred.")
}
Now that you have the fundamentals, you're ready to start building more complex logic and structures for your apps.