Comprehensive Swift Language Tutorial: Basics, Syntax, and Advanced Features
This extensive Swift tutorial introduces the language’s fundamentals—including variables, constants, control flow, functions, closures, enums, and memory management—while providing detailed code examples and explanations of advanced concepts such as protocols, generics, and ARC, making it a complete guide for iOS and macOS developers.
Swift is a modern, safe, and fast programming language for developing iOS, macOS, watchOS, and tvOS applications, offering features like Playgrounds for instant code preview without compilation.
It enforces safety through mandatory variable initialization, array bounds checking, integer overflow detection, optionals for nil handling, and automatic memory management, while providing robust error handling mechanisms.
Fundamentals
Constants and Variables
let maximumNumberOfLoginAttempts = 10
var currentLoginAttempt = 0
// type annotation
var welcomeMessage: StringComments
// This is a comment
/* This is a multi-line comment */
/* This is a nested comment
/* Nested */
End of first comment */Semicolons
let cat = "🐱"; print(cat)
// prints "🐱"Integers and Floating‑point Numbers
let minValue = UInt8.min // 0
let maxValue = UInt8.max // 255Type Safety and Type Inference
let meaningOfLife = 42 // inferred as Int
let pi = 3.14159 // inferred as DoubleNumeric Literals and Conversions
let decimalInteger = 17
let binaryInteger = 0b10001 // 17 in binary
let octalInteger = 0o21 // 17 in octal
let hexadecimalInteger = 0x11 // 17 in hexType Aliases
typealias AudioSample = UInt16
var maxAmplitudeFound = AudioSample.minBooleans
let orangesAreOrange = true
let turnipsAreDelicious = falseTuples let http404Error = (404, "Not Found") Optionals
var serverResponseCode: Int? = 404
serverResponseCode = nilError Handling
func makeASandwich() throws {
// ...
}
do {
try makeASandwich()
eatASandwich()
} catch SandwichError.outOfCleanDishes {
washDishes()
} catch SandwichError.missingIngredients(let ingredients) {
buyGroceries(ingredients)
}Assertions and Preconditions
let age = -3
assert(age >= 0, "A person's age cannot be less than zero")Basic Operators
Swift supports most standard C operators and adds range operators such as a..<b (half‑open) and a...b (closed).
let names = ["Anna", "Alex", "Brian", "Jack"]
let count = names.count
for i in 0..<count {
print("第 \(i + 1) 个人叫 \(names[i])")
}Strings and Characters
String literals, interpolation, character counting, concatenation, and comparison are demonstrated.
// Multi‑line string literal
let quotation = """
The White Rabbit put on his spectacles.
Where shall I begin, please your Majesty?
"""
let singleLineString = "These are the same."
let multilineString = """
These are the same.
"""
let multiplier = 3
let message = "\(multiplier) times 2.5 is \(Double(multiplier) * 2.5)"
var word = "cafe"
print("the number of characters in \(word) is \(word.count)")Collection Types
Arrays, Sets, and Dictionaries are introduced with examples of mutability and common operations.
// Array
var someInts = [Int]()
print("someInts is of type [Int] with \(someInts.count) items.")
var threeDoubles = Array(repeating: 0.0, count: 3)
var anotherThreeDoubles = Array(repeating: 2.5, count: 3)
var sixDoubles = threeDoubles + anotherThreeDoubles
var shoppingList: [String] = ["Eggs", "Milk"]
for (index, value) in shoppingList.enumerated() {
print("Item \(index + 1): \(value)")
}
// Dictionary
var numberOfLegs = ["spider": 8, "ant": 6, "cat": 4]
numberOfLegs["bird"] = 2Control Flow
For‑In loops, while/repeat‑while loops, guard statements, and API availability checks are shown.
let names = ["Anna", "Alex", "Brian", "Jack"]
for name in names {
print("Hello, \(name)!")
}
let numberOfLegs = ["spider": 8, "ant": 6, "cat": 4]
for (animalName, legCount) in numberOfLegs {
print("\(animalName)s have \(legCount) legs")
}
repeat {
// statements
} while condition
func greet(person: [String: String]) {
guard let name = person["name"] else { return }
print("Hello \(name)!")
guard let location = person["location"] else {
print("I hope the weather is nice near you.")
return
}
print("I hope the weather is nice in \(location).")
}Functions
Function definitions, parameter labels, return values, optional tuple returns, and inout parameters are covered.
func greet(person: String) -> String {
let greeting = "Hello, " + person + "!"
return greeting
}
func greet(person: String, from hometown: String) -> String {
return "Hello \(person)! Glad you could visit from \(hometown)."
}
func minMax(array: [Int]) -> (min: Int, max: Int)? {
if array.isEmpty { return nil }
var currentMin = array[0]
var currentMax = array[0]
for value in array[1..<array.count] {
if value < currentMin { currentMin = value }
else if value > currentMax { currentMax = value }
}
return (currentMin, currentMax)
}
func greeting(for person: String) -> String { "Hello, " + person + "!" }Closures
Closure syntax, trailing closures, value capture, escaping closures, and auto‑closures are illustrated.
let digitNames = [0: "Zero", 1: "One", 2: "Two", 3: "Three", 4: "Four", 5: "Five", 6: "Six", 7: "Seven", 8: "Eight", 9: "Nine"]
let numbers = [16, 58, 510]
let strings = numbers.map { (number) -> String in
var number = number
var output = ""
repeat {
output = digitNames[number % 10]! + output
number /= 10
} while number > 0
return output
}
func makeIncrementer(forIncrement amount: Int) -> () -> Int {
var runningTotal = 0
func incrementer() -> Int {
runningTotal += amount
return runningTotal
}
return incrementer
}
var customersInLine = ["Chris", "Alex", "Ewa", "Barry", "Daniella"]
print(customersInLine.count) // 5
let customerProvider = { customersInLine.remove(at: 0) }
print(customersInLine.count) // 5
print("Now serving \(customerProvider())!")
print(customersInLine.count) // 4Enumerations
Enum syntax, associated values, raw values, and recursive enums are demonstrated.
enum CompassPoint { case north, south, east, west }
enum Planet { case mercury, venus, earth, mars, jupiter, saturn, uranus, neptune }
let somePlanet = Planet.earth
switch somePlanet {
case .earth: print("Mostly harmless")
default: print("Not a safe place for humans")
}
enum Barcode { case upc(Int, Int, Int, Int); case qrCode(String) }
var productBarcode = Barcode.upc(8, 85909, 51226, 3)
productBarcode = .qrCode("ABCDEFGHIJKLMNOP")
switch productBarcode {
case let .upc(numberSystem, manufacturer, product, check):
print("UPC: \(numberSystem), \(manufacturer), \(product), \(check).")
case let .qrCode(productCode):
print("QR code: \(productCode).")
}
indirect enum ArithmeticExpression { case number(Int); case addition(ArithmeticExpression, ArithmeticExpression); case multiplication(ArithmeticExpression, ArithmeticExpression) }
let five = ArithmeticExpression.number(5)
let four = ArithmeticExpression.number(4)
let sum = ArithmeticExpression.addition(five, four)
let product = ArithmeticExpression.multiplication(sum, .number(2))
func evaluate(_ expression: ArithmeticExpression) -> Int {
switch expression {
case let .number(value): return value
case let .addition(left, right): return evaluate(left) + evaluate(right)
case let .multiplication(left, right): return evaluate(left) * evaluate(right)
}
}
print(evaluate(product)) // 18Structures and Classes
Definition, properties, methods, and differences between value and reference types are shown.
struct SomeStructure { }
class SomeClass { }
struct Resolution { var width = 0; var height = 0 }
class VideoMode { var resolution = Resolution(); var interlaced = false; var frameRate = 0.0; var name: String? }Properties
Stored, computed, property observers, property wrappers, and type properties are explained.
struct Point { var x = 0.0, y = 0.0 }
struct Size { var width = 0.0, height = 0.0 }
struct Rect {
var origin = Point()
var size = Size()
var center: Point {
get {
let centerX = origin.x + (size.width / 2)
let centerY = origin.y + (size.height / 2)
return Point(x: centerX, y: centerY)
}
set(newCenter) {
origin.x = newCenter.x - (size.width / 2)
origin.y = newCenter.y - (size.height / 2)
}
}
}
@propertyWrapper
struct TwelveOrLess {
private var number = 0
var wrappedValue: Int {
get { return number }
set { number = min(newValue, 12) }
}
}Methods
Instance and type (static) methods are illustrated.
class Counter {
var count = 0
func increment() { count += 1 }
func increment(by amount: Int) { count += amount }
func reset() { count = 0 }
}Subscripts
Subscript syntax for arrays, dictionaries, and static subscripts on enums is shown.
struct TimesTable { let multiplier: Int; subscript(index: Int) -> Int { return multiplier * index } }
let threeTimesTable = TimesTable(multiplier: 3)
print("six times three is \(threeTimesTable[6])") // 18
var numberOfLegs = ["spider": 8, "ant": 6, "cat": 4]
numberOfLegs["bird"] = 2
enum Planet: Int { case mercury = 1, venus, earth, mars, jupiter, saturn, uranus, neptune
static subscript(n: Int) -> Planet { return Planet(rawValue: n)! }
}
let mars = Planet[4]
print(mars)Inheritance
Base class, subclassing, overriding, and final are demonstrated.
class Vehicle {
var currentSpeed = 0.0
var description: String { return "traveling at \(currentSpeed) miles per hour" }
func makeNoise() {}
}
class Car: Vehicle {
var gear = 1
override var description: String { return super.description + " in gear \(gear)" }
}
class AutomaticCar: Car {
override var currentSpeed: Double {
didSet { gear = Int(currentSpeed / 10.0) + 1 }
}
}Initialization and Deinitialization
Designated and convenience initializers, failable initializers, required initializers, and deinit examples are provided.
struct Fahrenheit { var temperature: Double = 32.0 }
struct Color { let red, green, blue: Double; init(red: Double, green: Double, blue: Double) { self.red = red; self.green = green; self.blue = blue }
init(white: Double) { self.red = white; self.green = white; self.blue = white } }
class Bank { static var coinsInBank = 10_000; static func distribute(coins numberOfCoinsRequested: Int) -> Int { let numberOfCoinsToVend = min(numberOfCoinsRequested, coinsInBank); coinsInBank -= numberOfCoinsToVend; return numberOfCoinsToVend }
static func receive(coins: Int) { coinsInBank += coins } }
class Player { var coinsInPurse: Int; init(coins: Int) { coinsInPurse = Bank.distribute(coins: coins) }
func win(coins: Int) { coinsInPurse += Bank.distribute(coins: coins) }
deinit { Bank.receive(coins: coinsInPurse) } }Optional Chaining
class Person { var residence: Residence? }
class Residence { var numberOfRooms = 1 }
let john = Person()
if let roomCount = john.residence?.numberOfRooms {
print("John's residence has \(roomCount) room(s).")
} else {
print("Unable to retrieve the number of rooms.")
}
john.residence = Residence()
if let roomCount = john.residence?.numberOfRooms {
print("John's residence has \(roomCount) room(s).")
}Type Casting
class MediaItem { var name: String; init(name: String) { self.name = name } }
class Movie: MediaItem { var director: String; init(name: String, director: String) { self.director = director; super.init(name: name) } }
class Song: MediaItem { var artist: String; init(name: String, artist: String) { self.artist = artist; super.init(name: name) } }
let library: [MediaItem] = [Movie(name: "Casablanca", director: "Michael Curtiz"), Song(name: "Blue Suede Shoes", artist: "Elvis Presley"), Movie(name: "Citizen Kane", director: "Orson Welles"), Song(name: "The One And Only", artist: "Chesney Hawkes"), Song(name: "Never Gonna Give You Up", artist: "Rick Astley")]
for item in library {
if let movie = item as? Movie {
print("Movie: \(movie.name), dir. \(movie.director)")
} else if let song = item as? Song {
print("Song: \(song.name), by \(song.artist)")
}
}Nested Types
struct BlackjackCard {
enum Suit: Character { case spades = "1", hearts = "2", diamonds = "3", clubs = "4" }
enum Rank: Int {
case two = 2, three, four, five, six, seven, eight, nine, ten
case jack, queen, king, ace
struct Values { let first: Int; let second: Int? }
var values: Values {
switch self {
case .ace: return Values(first: 1, second: 11)
case .jack, .queen, .king: return Values(first: 10, second: nil)
default: return Values(first: self.rawValue, second: nil)
}
}
}
let rank: Rank, suit: Suit
var description: String {
var output = "suit is \(suit.rawValue), value is \(rank.values.first)"
if let second = rank.values.second { output += " or \(second)" }
return output
}
}
let theAceOfSpades = BlackjackCard(rank: .ace, suit: .spades)
print("theAceOfSpades: \(theAceOfSpades.description)")
let heartsSymbol = BlackjackCard.Suit.hearts.rawValueExtensions
Adding computed properties, initializers, methods, subscripts, and protocol conformance.
extension Rect {
init(center: Point, size: Size) {
let originX = center.x - (size.width / 2)
let originY = center.y - (size.height / 3)
self.init(origin: Point(x: originX, y: originY), size: size)
}
}
3.repetitions { print("Hello!") }
extension Int { mutating func square() { self = self * self } }
var someInt = 3
someInt.square() // now 9Protocols
protocol FullyNamed { var fullName: String { get } }
struct Person: FullyNamed { var fullName: String }
class Starship: FullyNamed {
var prefix: String?
var name: String
init(name: String, prefix: String? = nil) { self.name = name; self.prefix = prefix }
var fullName: String { return (prefix != nil ? prefix! + " " : "") + name }
}
let ncc1701 = Starship(name: "Enterprise", prefix: "USS")
print(ncc1701.fullName) // USS EnterpriseGenerics
func swapTwoValues<T>(_ a: inout T, _ b: inout T) {
let temporaryA = a
a = b
b = temporaryA
}
var someInt = 3, anotherInt = 107
swapTwoValues(&someInt, &anotherInt)
var someString = "hello", anotherString = "world"
swapTwoValues(&someString, &anotherString)Opaque Types
protocol Shape { func draw() -> String }
struct Triangle: Shape { var size: Int; func draw() -> String { var result = [String](); for length in 1...size { result.append(String(repeating: "*", count: length)) } return result.joined(separator: "
") } }
struct FlippedShape<T: Shape>: Shape { var shape: T; func draw() -> String { let lines = shape.draw().split(separator: "
"); return lines.reversed().joined(separator: "
") } }
let smallTriangle = Triangle(size: 3)
print(smallTriangle.draw())
let flippedTriangle = FlippedShape(shape: smallTriangle)
print(flippedTriangle.draw())Automatic Reference Counting (ARC)
class Person { let name: String; init(name: String) { self.name = name; print("\(name) is being initialized") } deinit { print("\(name) is being deinitialized") } var apartment: Apartment? }
class Apartment { let unit: String; init(unit: String) { self.unit = unit } weak var tenant: Person? deinit { print("Apartment \(unit) is being deinitialized") } }
var john: Person? = Person(name: "John Appleseed")
var unit4A: Apartment? = Apartment(unit: "4A")
john!.apartment = unit4A
unit4A!.tenant = john
john = nil // Person deinitialized, apartment remains because of weak referenceMemory Safety
func balance(_ x: inout Int, _ y: inout Int) {
let sum = x + y
x = sum / 2
y = sum - x
}
var playerOneScore = 42
var playerTwoScore = 30
balance(&playerOneScore, &playerTwoScore) // ok
// balance(&playerOneScore, &playerOneScore) // error: conflictAccess Control
Explanation of open, public, internal, fileprivate, and private levels with examples.
public class SomePublicClass {}
internal class SomeInternalClass {}
fileprivate class SomeFilePrivateClass {}
private class SomePrivateClass {}
public class SomePublicClass {
public var somePublicProperty = 0
var someInternalProperty = 0
fileprivate func someFilePrivateMethod() {}
private func somePrivateMethod() {}
}Advanced Operators
let initialBits: UInt8 = 0b00001111
let invertedBits = ~initialBits // 0b11110000
var potentialOverflow = Int16.max
// potentialOverflow += 1 // overflow error
struct Vector2D { var x = 0.0, y = 0.0 }
extension Vector2D { static func + (left: Vector2D, right: Vector2D) -> Vector2D { return Vector2D(x: left.x + right.x, y: left.y + right.y) } }
let vector = Vector2D(x: 3.0, y: 1.0)
let anotherVector = Vector2D(x: 2.0, y: 4.0)
let combinedVector = vector + anotherVector // (5.0, 5.0)Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Wukong Talks Architecture
Explaining distributed systems and architecture through stories. Author of the "JVM Performance Tuning in Practice" column, open-source author of "Spring Cloud in Practice PassJava", and independently developed a PMP practice quiz mini-program.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
