Swift
Programming Language
Swift
Overview
Swift is a modern programming language developed by Apple for iOS/macOS app development.
Details
Swift is a modern programming language announced by Apple in 2014 for developing applications for iOS, macOS, watchOS, and tvOS. Designed as a successor to Objective-C, it emphasizes safety, performance, and expressiveness. Features like type safety, automatic memory management, and nil safety enable writing safer and more maintainable code. Swift was open-sourced in 2015, making it available on platforms beyond Apple's ecosystem. The introduction of SwiftUI has enabled declarative UI development, significantly improving iOS development efficiency. Currently, many apps on the App Store are developed in Swift, establishing it as the standard language for iOS/macOS app development.
Usage Examples
Hello World
// Basic output
print("Hello, World!")
// Multiple value output
print("Hello,", "Swift!")
// Output using variables
let message = "Hello, Swift!"
print(message)
// String interpolation
let name = "John"
let age = 25
print("My name is \(name) and I am \(age) years old.")
// Multi-line strings
let multiline = """
This is a multi-line
string.
Very Swift-like syntax.
"""
print(multiline)
// Debug output
debugPrint("This is debug output")
// Output with file name and line number
print("Error occurred", #file, #line)
// Basic structure for Playground and iOS apps
import Foundation
// For iOS apps (UIKit)
/*
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
print("Hello from iOS app!")
}
}
*/
// For SwiftUI apps
/*
import SwiftUI
struct ContentView: View {
var body: some View {
Text("Hello, SwiftUI!")
}
}
*/
Variables and Data Types
// Variables and constants
var mutableValue = 42 // Mutable variable
let immutableValue = 100 // Immutable constant
// Type annotations (explicit type specification)
var explicitInt: Int = 50
var explicitString: String = "Hello"
// Basic data types
let integer: Int = 42
let floatingPoint: Double = 3.14159
let singlePrecision: Float = 2.71828
let boolean: Bool = true
let character: Character = "A"
let string: String = "Swift Programming"
// Type inference
let inferredInt = 123 // Inferred as Int
let inferredDouble = 3.14 // Inferred as Double
let inferredString = "Hello" // Inferred as String
// Number representations
let binary = 0b1010 // Binary
let octal = 0o755 // Octal
let hexadecimal = 0xFF // Hexadecimal
let scientific = 1.25e2 // Scientific notation
// Optional types (nil-compatible types)
var optionalString: String? = "Has value"
var nilValue: String? = nil
// Optional binding (safe value extraction)
if let unwrappedString = optionalString {
print("Value: \(unwrappedString)")
} else {
print("No value")
}
// Guard statement for Optional handling
func processOptional(_ value: String?) {
guard let unwrappedValue = value else {
print("No value")
return
}
print("Processing: \(unwrappedValue)")
}
// Nil coalescing operator
let defaultValue = optionalString ?? "Default value"
print("Value: \(defaultValue)")
// Arrays
var fruits = ["apple", "banana", "orange"]
let numbers: [Int] = [1, 2, 3, 4, 5]
var emptyArray: [String] = []
// Array operations
fruits.append("strawberry")
fruits.insert("grape", at: 0)
fruits.remove(at: 1)
// Dictionary
var person = [
"name": "John Doe",
"age": "30",
"city": "New York"
]
// Typed dictionary
let scores: [String: Int] = [
"Math": 85,
"English": 92,
"Science": 78
]
// Set (unique collection)
var uniqueNumbers: Set<Int> = [1, 2, 3, 4, 5]
uniqueNumbers.insert(3) // Duplicates not added
// Tuples
let coordinates = (x: 10.0, y: 20.0)
let httpStatus = (statusCode: 200, description: "OK")
// Accessing tuple elements
print("X coordinate: \(coordinates.x)")
print("Status: \(httpStatus.statusCode)")
// Type aliases
typealias Point = (x: Double, y: Double)
typealias UserInfo = [String: String]
let point: Point = (x: 5.0, y: 10.0)
let user: UserInfo = ["name": "Smith", "email": "[email protected]"]
// Type checking
print(type(of: integer)) // Int
print(type(of: string)) // String
print(type(of: fruits)) // Array<String>
// Type conversion
let stringNumber = "123"
let convertedNumber = Int(stringNumber) ?? 0
let numberAsString = String(integer)
print("String to number: \(convertedNumber)")
print("Number to string: \(numberAsString)")
print("Array: \(fruits)")
print("Dictionary: \(person)")
print("Set: \(uniqueNumbers)")
print("Tuple: \(coordinates)")
Functions and Closures
// Basic function
func add(_ a: Int, _ b: Int) -> Int {
return a + b
}
// Single-expression function (return can be omitted)
func multiply(_ a: Int, _ b: Int) -> Int {
a * b
}
// Function with argument labels
func greet(person name: String, from hometown: String) -> String {
return "Hello, \(name) from \(hometown)!"
}
// Default arguments
func createUser(name: String, age: Int = 0, email: String = "") -> [String: Any] {
return [
"name": name,
"age": age,
"email": email
]
}
// Variadic parameters
func sum(_ numbers: Int...) -> Int {
return numbers.reduce(0, +)
}
// inout parameters (pass by reference)
func swapValues(_ a: inout Int, _ b: inout Int) {
let temp = a
a = b
b = temp
}
// Function returning function
func makeIncrementer(incrementAmount: Int) -> () -> Int {
var total = 0
return {
total += incrementAmount
return total
}
}
// Function taking function as parameter
func processArray(_ array: [Int], using operation: (Int) -> Int) -> [Int] {
return array.map(operation)
}
// Function usage examples
print(add(5, 3))
print(multiply(4, 6))
print(greet(person: "Smith", from: "London"))
let user1 = createUser(name: "Johnson")
let user2 = createUser(name: "Brown", age: 25, email: "[email protected]")
print("Total: \(sum(1, 2, 3, 4, 5))")
var x = 10
var y = 20
swapValues(&x, &y)
print("After swap: x=\(x), y=\(y)")
// Closures
let incrementByTwo = makeIncrementer(incrementAmount: 2)
print("Increment: \(incrementByTwo())")
print("Increment: \(incrementByTwo())")
// Various closure syntaxes
let numbers = [1, 2, 3, 4, 5]
// Full form
let doubled1 = numbers.map({ (number: Int) -> Int in
return number * 2
})
// Using type inference
let doubled2 = numbers.map({ number in
return number * 2
})
// Single-expression closures
let doubled3 = numbers.map({ number in number * 2 })
// Shorthand argument names
let doubled4 = numbers.map({ $0 * 2 })
// Trailing closures
let doubled5 = numbers.map { $0 * 2 }
// Higher-order function examples
let evens = numbers.filter { $0 % 2 == 0 }
let total = numbers.reduce(0) { $0 + $1 }
let strings = numbers.map { "Number: \($0)" }
print("Doubled: \(doubled5)")
print("Evens: \(evens)")
print("Total: \(total)")
print("Strings: \(strings)")
// Escaping closures
func fetchData(completion: @escaping (String) -> Void) {
DispatchQueue.global().async {
// Simulate async processing
Thread.sleep(forTimeInterval: 1)
DispatchQueue.main.async {
completion("Data fetched successfully")
}
}
}
// Usage example (runs asynchronously in actual apps)
// fetchData { result in
// print(result)
// }
// Autoclosures
func logIfDebug(_ message: @autoclosure () -> String, isDebug: Bool = true) {
if isDebug {
print("DEBUG: \(message())")
}
}
logIfDebug("Important info: \(Date())")
Structures and Classes
// Structure definition
struct Person {
var name: String
var age: Int
let id: String = UUID().uuidString
// Computed property
var description: String {
return "\(name) (\(age) years old) - ID: \(id)"
}
// Property observers
var email: String = "" {
willSet {
print("About to change email to \(newValue)")
}
didSet {
print("Changed email from \(oldValue) to \(email)")
}
}
// Initializer
init(name: String, age: Int) {
self.name = name
self.age = age
}
// Methods
func introduce() -> String {
return "My name is \(name) and I am \(age) years old."
}
// Mutating methods (modify struct properties)
mutating func haveBirthday() {
age += 1
print("Happy \(age)th birthday, \(name)!")
}
// Static methods
static func createUnknownPerson() -> Person {
return Person(name: "Unknown", age: 0)
}
}
// Class definition
class Vehicle {
var brand: String
var model: String
var year: Int
// Designated initializer
init(brand: String, model: String, year: Int) {
self.brand = brand
self.model = model
self.year = year
}
// Convenience initializer
convenience init(brand: String, model: String) {
self.init(brand: brand, model: model, year: 2024)
}
func description() -> String {
return "\(year) \(brand) \(model)"
}
// Deinitializer
deinit {
print("\(description()) has been deallocated")
}
}
// Inheritance
class Car: Vehicle {
var numberOfDoors: Int
init(brand: String, model: String, year: Int, numberOfDoors: Int) {
self.numberOfDoors = numberOfDoors
super.init(brand: brand, model: model, year: year)
}
override func description() -> String {
return "\(super.description()) - \(numberOfDoors) doors"
}
func startEngine() {
print("Started \(brand) \(model) engine")
}
}
// Protocol definition
protocol Drawable {
func draw()
var area: Double { get }
}
protocol Colorable {
var color: String { get set }
}
// Protocol implementation
struct Circle: Drawable, Colorable {
var radius: Double
var color: String
var area: Double {
return Double.pi * radius * radius
}
func draw() {
print("Drawing a \(color) circle with radius \(radius)")
}
}
// Enumerations
enum Direction {
case north, south, east, west
func description() -> String {
switch self {
case .north: return "North"
case .south: return "South"
case .east: return "East"
case .west: return "West"
}
}
}
// Enums with associated values
enum Result<T> {
case success(T)
case failure(Error)
func getValue() -> T? {
switch self {
case .success(let value):
return value
case .failure(_):
return nil
}
}
}
// Usage examples
print("=== Structures and Classes Usage ===")
// Structure usage
var person1 = Person(name: "John Doe", age: 25)
print(person1.introduce())
print(person1.description)
person1.email = "[email protected]"
person1.haveBirthday()
let unknownPerson = Person.createUnknownPerson()
print(unknownPerson.introduce())
// Class usage
let vehicle = Vehicle(brand: "Toyota", model: "Prius")
print(vehicle.description())
let car = Car(brand: "Honda", model: "Civic", year: 2023, numberOfDoors: 4)
print(car.description())
car.startEngine()
// Protocol usage
let circle = Circle(radius: 5.0, color: "red")
circle.draw()
print("Area: \(circle.area)")
// Enum usage
let direction = Direction.north
print("Direction: \(direction.description())")
let successResult: Result<String> = .success("Data fetched successfully")
let failureResult: Result<String> = .failure(NSError(domain: "NetworkError", code: 404, userInfo: nil))
if let value = successResult.getValue() {
print("Success: \(value)")
}
// Value types vs Reference types
var person2 = person1 // Structs are value types, so they are copied
person2.name = "Jane Smith"
print("person1: \(person1.name)") // "John Doe"
print("person2: \(person2.name)") // "Jane Smith"
let car1 = car // Classes are reference types, so they reference same instance
car1.brand = "Nissan"
print("car.brand: \(car.brand)") // "Nissan"
print("car1.brand: \(car1.brand)") // "Nissan"
Error Handling
// Error definition
enum ValidationError: Error {
case emptyName
case invalidAge(Int)
case invalidEmail(String)
case networkError(code: Int, message: String)
}
// Providing error details
extension ValidationError: LocalizedError {
var errorDescription: String? {
switch self {
case .emptyName:
return "Name is empty"
case .invalidAge(let age):
return "Invalid age: \(age)"
case .invalidEmail(let email):
return "Invalid email address: \(email)"
case .networkError(let code, let message):
return "Network error (\(code)): \(message)"
}
}
}
// Function using throws keyword
func validateUser(name: String, age: Int, email: String) throws -> [String: Any] {
// Name validation
guard !name.isEmpty else {
throw ValidationError.emptyName
}
// Age validation
guard age >= 0 && age <= 150 else {
throw ValidationError.invalidAge(age)
}
// Email validation
let emailRegex = #"^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$"#
guard email.range(of: emailRegex, options: .regularExpression) != nil else {
throw ValidationError.invalidEmail(email)
}
return [
"name": name,
"age": age,
"email": email,
"id": UUID().uuidString
]
}
// Function simulating network processing
func fetchDataFromServer() throws -> String {
let shouldSucceed = Bool.random()
if shouldSucceed {
return "Data fetched from server"
} else {
throw ValidationError.networkError(code: 500, message: "Internal Server Error")
}
}
// Function with retry functionality
func fetchDataWithRetry(maxAttempts: Int = 3) throws -> String {
var attempts = 0
while attempts < maxAttempts {
attempts += 1
do {
let data = try fetchDataFromServer()
print("Succeeded on attempt \(attempts)")
return data
} catch {
print("Attempt \(attempts) failed: \(error)")
if attempts == maxAttempts {
throw error
}
// Wait a bit before retry
Thread.sleep(forTimeInterval: 0.1)
}
}
// This line won't be reached, but prevents compiler error
throw ValidationError.networkError(code: 999, message: "Unexpected error")
}
// Exception handling with do-catch
print("=== Error Handling ===")
// Normal case
do {
let user = try validateUser(name: "John Doe", age: 30, email: "[email protected]")
print("User creation successful: \(user)")
} catch ValidationError.emptyName {
print("Error: Name is empty")
} catch ValidationError.invalidAge(let age) {
print("Error: Invalid age - \(age)")
} catch ValidationError.invalidEmail(let email) {
print("Error: Invalid email - \(email)")
} catch {
print("Unexpected error: \(error)")
}
// Testing various error cases
let testCases = [
("", 25, "[email protected]"), // Empty name
("Jane Smith", -5, "[email protected]"), // Invalid age
("Bob Johnson", 30, "invalid-email"), // Invalid email
("Alice Brown", 25, "[email protected]") // Normal case
]
for (name, age, email) in testCases {
do {
let user = try validateUser(name: name, age: age, email: email)
print("✅ User creation successful: \(user["name"] ?? "Unknown")")
} catch let error as ValidationError {
print("❌ Validation error: \(error.localizedDescription)")
} catch {
print("❌ Other error: \(error)")
}
}
// Using try? and try!
print("\n=== try? and try! ===")
// try? - returns nil if fails
let optionalUser1 = try? validateUser(name: "Test User 1", age: 25, email: "[email protected]")
if let user = optionalUser1 {
print("✅ Optional user creation successful: \(user)")
} else {
print("❌ User creation failed")
}
let optionalUser2 = try? validateUser(name: "", age: 25, email: "[email protected]")
print("Result with empty name: \(optionalUser2 == nil ? "nil" : "has value")")
// try! - crashes if fails (use with caution)
// let forcedUser = try! validateUser(name: "Forced User", age: 25, email: "[email protected]")
// print("Forced result: \(forcedUser)")
// defer statement - always executed at scope end
func processFile() {
print("Starting file processing")
defer {
print("File processing cleanup")
}
defer {
print("Closing file")
}
do {
let data = try fetchDataFromServer()
print("Data processing: \(data)")
} catch {
print("Error during file processing: \(error)")
}
print("Main file processing completed")
}
processFile()
// Error handling with Result type
func validateUserAsResult(name: String, age: Int, email: String) -> Result<[String: Any], ValidationError> {
do {
let user = try validateUser(name: name, age: age, email: email)
return .success(user)
} catch let error as ValidationError {
return .failure(error)
} catch {
return .failure(.networkError(code: 999, message: "Unknown error"))
}
}
let result = validateUserAsResult(name: "Result User", age: 28, email: "[email protected]")
switch result {
case .success(let user):
print("✅ Result success: \(user["name"] ?? "Unknown")")
case .failure(let error):
print("❌ Result failure: \(error.localizedDescription)")
}
// Retry processing example
print("\n=== Retry Processing ===")
do {
let data = try fetchDataWithRetry(maxAttempts: 3)
print("✅ Retry success: \(data)")
} catch {
print("❌ Final retry failure: \(error)")
}
SwiftUI Basics
// SwiftUI is a declarative UI framework
// Below are basic SwiftUI examples
import SwiftUI
// Basic View
struct ContentView: View {
@State private var name: String = ""
@State private var age: String = ""
@State private var showAlert = false
@State private var message = ""
var body: some View {
NavigationView {
VStack(spacing: 20) {
// Header
Text("User Registration")
.font(.largeTitle)
.fontWeight(.bold)
// Input fields
VStack(spacing: 15) {
TextField("Enter name", text: $name)
.textFieldStyle(RoundedBorderTextFieldStyle())
TextField("Enter age", text: $age)
.textFieldStyle(RoundedBorderTextFieldStyle())
.keyboardType(.numberPad)
}
.padding(.horizontal)
// Button
Button(action: registerUser) {
Text("Register")
.foregroundColor(.white)
.padding()
.frame(maxWidth: .infinity)
.background(Color.blue)
.cornerRadius(10)
}
.padding(.horizontal)
.disabled(name.isEmpty || age.isEmpty)
Spacer()
}
.navigationTitle("App")
.alert("Result", isPresented: $showAlert) {
Button("OK") { }
} message: {
Text(message)
}
}
}
private func registerUser() {
guard let ageInt = Int(age) else {
message = "Please enter a valid age"
showAlert = true
return
}
// Use validation function (defined above)
do {
let user = try validateUser(name: name, age: ageInt, email: "\(name.lowercased())@example.com")
message = "Registered user '\(user["name"] ?? "Unknown")'"
showAlert = true
// Clear fields
name = ""
age = ""
} catch let error as ValidationError {
message = "Registration error: \(error.localizedDescription)"
showAlert = true
} catch {
message = "An unexpected error occurred"
showAlert = true
}
}
}
// List display View
struct UserListView: View {
@State private var users: [[String: Any]] = []
var body: some View {
NavigationView {
List {
ForEach(users.indices, id: \.self) { index in
UserRowView(user: users[index])
}
.onDelete(perform: deleteUsers)
}
.navigationTitle("User List")
.onAppear(perform: loadUsers)
.toolbar {
ToolbarItem(placement: .navigationBarTrailing) {
Button("Add") {
addSampleUser()
}
}
}
}
}
private func loadUsers() {
// Load sample users
users = [
["name": "John Doe", "age": 30, "email": "[email protected]"],
["name": "Jane Smith", "age": 25, "email": "[email protected]"],
["name": "Bob Johnson", "age": 35, "email": "[email protected]"]
]
}
private func addSampleUser() {
let newUser = [
"name": "New User \(users.count + 1)",
"age": Int.random(in: 20...60),
"email": "user\(users.count + 1)@example.com"
] as [String : Any]
users.append(newUser)
}
private func deleteUsers(offsets: IndexSet) {
users.remove(atOffsets: offsets)
}
}
// User row View
struct UserRowView: View {
let user: [String: Any]
var body: some View {
HStack {
VStack(alignment: .leading, spacing: 4) {
Text(user["name"] as? String ?? "Unknown")
.font(.headline)
Text("\(user["age"] as? Int ?? 0) years old")
.font(.subheadline)
.foregroundColor(.secondary)
Text(user["email"] as? String ?? "")
.font(.caption)
.foregroundColor(.blue)
}
Spacer()
Image(systemName: "person.fill")
.foregroundColor(.gray)
}
.padding(.vertical, 4)
}
}
// App entry point
@main
struct MyApp: App {
var body: some Scene {
WindowGroup {
TabView {
ContentView()
.tabItem {
Image(systemName: "person.badge.plus")
Text("Register")
}
UserListView()
.tabItem {
Image(systemName: "list.bullet")
Text("List")
}
}
}
}
}
// Preview (for Xcode preview)
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
// Custom modifier example
struct PrimaryButtonStyle: ViewModifier {
func body(content: Content) -> some View {
content
.foregroundColor(.white)
.padding()
.background(Color.blue)
.cornerRadius(10)
.shadow(radius: 5)
}
}
extension View {
func primaryButtonStyle() -> some View {
modifier(PrimaryButtonStyle())
}
}
// Usage example
// Button("Test Button") { }
// .primaryButtonStyle()
print("SwiftUI code examples defined. They work in actual Xcode projects.")
Versions
Version | Release Date | Major Features |
---|---|---|
Swift 5.9 | Sept 2023 | Macros, if-else expressions, Parameter packs |
Swift 5.8 | March 2023 | Function back deployment, Collection downcasts |
Swift 5.7 | Sept 2022 | Regex literals, Generic protocols |
Swift 5.6 | March 2022 | Type placeholders, ConcurrentValue protocol |
Swift 5.5 | Sept 2021 | Async/await, Actors, Structured concurrency |
Swift 5.4 | April 2021 | Multiple variadic parameters, Result builders |
Swift 5.3 | Sept 2020 | Multi-pattern catch clauses, @main attribute |
Reference Links
Official Documentation
- Swift Official Site - Swift official website
- Swift Documentation - Official documentation
- Apple Developer Swift - Apple developer Swift information
Learning Resources
- Swift Programming Language - Official Swift language guide
- Swift by Sundell - Swift learning blog
- Hacking with Swift - Comprehensive Swift learning site
Development Tools & Frameworks
- Xcode - Swift development IDE
- SwiftUI - Declarative UI framework
- Swift Package Manager - Package management tool
- Vapor - Server-side Swift framework