Coding · Programming languages
Swift tutorial for beginners
Short answer
Swift is a fast, safe, compiled language created by Apple for iPhone, iPad, Mac, Apple Watch and Apple TV apps, and it also runs on Linux and Windows. Save print("Hello, world") in hello.swift and run swift hello.swift. The core ideas are let constants and var variables, type inference, optionals for values that may be missing, structs and enums with value semantics, protocols, and errors handled with do/try/catch.
What Swift is and what it is used for
Swift was introduced by Apple in 2014 as a modern replacement for Objective-C and was open-sourced in 2015; the project lives at swift.org. It is the main language for apps on Apple platforms, usually with the SwiftUI or UIKit frameworks. Swift is also used for server-side code (for example with the Vapor framework) and command-line tools. The language is designed to prevent common bugs: variables must be initialized, arrays check their bounds, and nil must be handled explicitly.
Install Swift and run Hello, world
On a Mac, install Xcode from the App Store or the Xcode command-line tools. On Linux and Windows, download a toolchain from swift.org. Check it with swift --version.
print("Hello, world")swift hello.swift
# Hello, world
swiftc hello.swift -o hello # compile to a binary
./helloFor a larger project, run swift package init --type executable and then swift run. Xcode playgrounds are another easy way to experiment.
Constants, variables and basic types
Use let for constants and var for variables. Prefer let; the compiler warns when a var is never changed. Types are inferred, and Swift never converts between numeric types implicitly.
| Type | Example | Notes |
|---|---|---|
Int | let n = 42 | 64-bit on modern platforms |
Double | let x = 3.14 | Default floating-point type |
Bool | let ok = true | true or false |
String | let s = "hi \(name)" | Unicode text, value type |
Character | let c: Character = "é" | One user-perceived character |
[Int], [String: Int] | [1, 2], ["a": 1] | Array and dictionary |
let name = "Ada"
var count = 7
count += 1
let avg = Double(count) / 2 // explicit conversion
print("\(name) has \(count) items, avg \(avg)") // Ada has 8 items, avg 4.0
print(7 / 2, 7 % 2) // 3 1\(expression) inside a string literal inserts a value (string interpolation).
Control flow
let score = 72
if score >= 90 {
print("A")
} else if score >= 70 {
print("B") // B
} else {
print("C")
}
for i in 0..<3 {
print(i, terminator: " ") // 0 1 2
}
print()
var n = 10
while n > 1 { n /= 2 }
print(n) // 1
let day = "SAT"
switch day {
case "SAT", "SUN":
print("weekend") // weekend
default:
print("weekday")
}switch must be exhaustive, does not fall through by default, and can match ranges (case 90...100:), tuples and enum cases.
Functions and closures
Parameters have argument labels that callers write, which makes calls read like sentences. Use _ to omit a label. Closures are unnamed functions written in braces.
func greet(_ name: String, with greeting: String = "Hello") -> String {
return "\(greeting), \(name)!"
}
print(greet("Lin")) // Hello, Lin!
print(greet("Lin", with: "Hi")) // Hi, Lin!
let nums = [3, 1, 2, 5]
let squares = nums.map { $0 * $0 }
let evens = nums.filter { $0 % 2 == 0 }
let sorted = nums.sorted(by: >)
print(squares, evens, sorted) // [9, 1, 4, 25] [2] [5, 3, 2, 1]$0 refers to the first closure argument. When a closure is the last argument, it can be written after the parentheses (trailing closure syntax).
Arrays, dictionaries and sets
var fruits = ["apple", "pear"]
fruits.append("fig")
print(fruits.count, fruits[0], fruits.contains("fig")) // 3 apple true
var ages: [String: Int] = ["ann": 31, "bob": 25]
ages["cy"] = 40
for (person, age) in ages.sorted(by: { $0.key < $1.key }) {
print(person, age) // ann 31, bob 25, cy 40
}
print(ages["zed", default: 0]) // 0
let tags: Set = ["b", "a", "b"]
print(tags.count) // 2Collections are value types: assigning an array to another variable creates an independent copy (copied lazily, only when one of them changes). A let array cannot be modified at all.
Signature feature: optionals
A value that may be missing has an optional type, written String?. You cannot use it as a String until you unwrap it, so the compiler forces you to handle the nil case.
let input = "42"
let number: Int? = Int(input) // nil if input is not a number
if let number { // unwrap: runs only when not nil
print("got \(number)") // got 42
}
func firstWord(_ text: String) -> String? {
text.split(separator: " ").first.map(String.init)
}
guard let word = firstWord("hello world") else {
fatalError("no words")
}
print(word) // hello
print(firstWord("")?.uppercased() ?? "none") // noneif let and guard let unwrap safely, ?. (optional chaining) calls a method only when the value exists, and ?? supplies a default. The force unwrap value! crashes when the value is nil, so use it rarely. The short form if let number needs Swift 5.7 or later.
Structs, classes, enums and protocols
Structs and enums are value types; classes are reference types with inheritance. Swift code favors structs and protocols (interfaces) over class hierarchies.
protocol Shape {
func area() -> Double
}
struct Rect: Shape {
var width: Double
var height: Double
func area() -> Double { width * height }
}
enum Circle: Shape {
case unit
case radius(Double)
func area() -> Double {
switch self {
case .unit: return Double.pi
case .radius(let r): return Double.pi * r * r
}
}
}
let shapes: [any Shape] = [Rect(width: 2, height: 3), Circle.radius(1)]
let total = shapes.reduce(0) { $0 + $1.area() }
print((total * 100).rounded() / 100) // 9.14Structs get a memberwise initializer automatically (Rect(width:height:)). Enum cases can carry associated values, as .radius(Double) does.
Error handling
Functions that can fail are marked throws. Callers must use try inside a do/catch block, or use try? to turn an error into nil.
enum AgeError: Error {
case notANumber(String)
case negative
}
func parseAge(_ text: String) throws -> Int {
guard let age = Int(text) else { throw AgeError.notANumber(text) }
guard age >= 0 else { throw AgeError.negative }
return age
}
do {
print(try parseAge("41")) // 41
print(try parseAge("abc"))
} catch AgeError.notANumber(let text) {
print("not a number: \(text)") // not a number: abc
} catch {
print("other error: \(error)")
}
let maybe = try? parseAge("-3") // nil
print(maybe as Any) // nilA small complete program: word frequency
import Foundation
let args = CommandLine.arguments
guard args.count == 2 else {
print("usage: swift words.swift FILE")
exit(1)
}
do {
let text = try String(contentsOfFile: args[1], encoding: .utf8).lowercased()
let words = text.split { !$0.isLetter && $0 != "'" }
var counts: [Substring: Int] = [:]
for word in words {
counts[word, default: 0] += 1
}
for (word, n) in counts.sorted(by: { $0.value > $1.value }).prefix(5) {
print(String(n).padding(toLength: 6, withPad: " ", startingAt: 0) + word)
}
} catch {
print("cannot read \(args[1]): \(error.localizedDescription)")
exit(1)
}Run it with swift words.swift notes.txt. Foundation provides file reading and string helpers; it is available on Apple platforms and in the Linux and Windows toolchains.
Common beginner mistakes
- Trying to change a
letconstant or a property of aletstruct. Usevarwhen the value must change. - Expecting a struct to be shared like an object. Changing a copy does not change the original; use a class if you need shared identity.
- Indexing a
Stringwith an integer, such ass[0]. Uses.first,s.prefix(3)orString.Indexvalues. - Mixing
IntandDoublein arithmetic without converting, which is a compile error. - Forgetting
trybefore a throwing call, or usingtry!, which crashes on error.
Where to go next
Read "The Swift Programming Language" on docs.swift.org, the official guide and reference, and the documentation hub on swift.org. For apps, follow Apple's SwiftUI tutorials in Xcode. Then learn Swift concurrency (async/await and actors), generics, and the Swift Package Manager for dependencies.
FAQ
Is Swift only for Apple platforms?
No. Swift is open source and runs on Linux and Windows too, and it is used for server-side code and tools. However, app frameworks such as SwiftUI and UIKit are Apple-only.
Should I learn Swift or Objective-C?
Learn Swift. It is Apple's recommended language for new apps, and it can call existing Objective-C code when needed.
What is the difference between a struct and a class in Swift?
A struct is a value type that is copied when assigned or passed; a class is a reference type, so all variables share one instance. Classes also support inheritance and deinitializers.
What does the question mark after a type mean?
Int? is an optional: it holds either an Int or nil. You must unwrap it, for example with if let, before using the value.