Swift Cheatsheet¶
Swift - Apples Leistungsstarke und intuitive Programming Language
Swift ist eine leistungsstarke und intuitive Programmiersprache für iOS, macOS, watchOS und tvOS. Schreiben Swift-Code ist interaktiv und Spaß, die Syntax ist prägnant noch expressiv, und Swift enthält moderne Features Entwickler Liebe. < p>
Inhaltsverzeichnis¶
- [Installation](#installation
- Basic Syntax
- Variablen und Konstanten
- Datentypen
- (Operatoren)(LINK_4__)
- [Control Flow](#control-flow_
- Funktionen
- (#closures_)
- [Klassen und Strukturen](#classes-and-structures
- [Properties](LINK_9_
- Methoden
- Erinnerung
- Protokolle
- Erweiterungen
- [Generika](LINK_14__
- [Fehlerbehandlung](#error-handling
- [Memory Management](LINK_16__
- [Koncurrency](LINK_17_
- (#collections)
- Optionen
- Beste Praktiken
Installation¶
Xcode Installation¶
# Install Xcode from Mac App Store
# Xcode includes Swift compiler and runtime
# Verify Swift installation
swift --version
# Swift REPL (Read-Eval-Print Loop)
swift
# Swift Package Manager
swift package init
swift build
swift run
```_
### Swift auf Linux
```bash
# Download Swift for Linux from swift.org
# Extract and add to PATH
# Ubuntu/Debian
sudo apt-get install clang libicu-dev
# Install Swift
tar xzf swift-5.8-RELEASE-ubuntu20.04.tar.gz
export PATH=/path/to/swift-5.8-RELEASE-ubuntu20.04/usr/bin:$PATH
# Verify installation
swift --version
```_
## Grundprinzip
### Hallo Welt
```swift
// Simple print statement
print("Hello, World!")
// Multi-line string
let multilineString = """
This is a
multi-line string
in Swift
"""
print(multilineString)
// String interpolation
let name = "Swift"
let version = 5.8
print("Hello, \(name) \(version)!")
// Comments
// This is a single-line comment
/*
This is a
multi-line comment
*/
/// This is a documentation comment
/// - Parameter name: The name to greet
/// - Returns: A greeting string
func greet(name: String) -> String {
return "Hello, \(name)!"
}
```_
### Semikolonen und Line Breaks
```swift
// Semicolons are optional
let a = 1
let b = 2
// Multiple statements on one line require semicolons
let x = 1; let y = 2
// Line breaks are used to separate statements
let firstName = "John"
let lastName = "Doe"
let fullName = firstName + " " + lastName
```_
## Variablen und Konstanten
### Erklärung
```swift
// Variables (mutable)
var variableName = "I can change"
var age = 25
var height: Double = 5.9
// Constants (immutable)
let constantName = "I cannot change"
let pi = 3.14159
let maxUsers: Int = 100
// Type annotation
var explicitString: String = "This is a string"
var explicitInt: Int = 42
var explicitDouble: Double = 3.14
// Multiple variable declaration
var x = 0.0, y = 0.0, z = 0.0
// Deferred initialization
let deferredConstant: String
if someCondition {
deferredConstant = "Value A"
} else {
deferredConstant = "Value B"
}
```_
### Namenskonventionen
```swift
// Use camelCase for variables and functions
var userName = "john_doe"
var isLoggedIn = true
func calculateTotalPrice() -> Double { return 0.0 }
// Use PascalCase for types
class UserManager { }
struct DatabaseConnection { }
enum NetworkError { }
// Use SCREAMING_SNAKE_CASE for constants
let MAX_RETRY_COUNT = 3
let API_BASE_URL = "https://api.example.com"
// Use descriptive names
var currentUserAge = 25 // Good
var a = 25 // Bad
// Boolean variables should be questions
var isVisible = true
var hasPermission = false
var canEdit = true
```_
## Datentypen
### Grundtypen
```swift
// Integer types
let smallInt: Int8 = 127
let mediumInt: Int16 = 32767
let normalInt: Int32 = 2147483647
let bigInt: Int64 = 9223372036854775807
let unsignedInt: UInt = 42
// Floating-point types
let floatNumber: Float = 3.14159
let doubleNumber: Double = 3.141592653589793
// Boolean
let isTrue: Bool = true
let isFalse: Bool = false
// Character and String
let singleCharacter: Character = "A"
let stringValue: String = "Hello, Swift!"
// Type inference
let inferredInt = 42 // Int
let inferredDouble = 3.14 // Double
let inferredString = "Text" // String
let inferredBool = true // Bool
```_
### String Manipulation
```swift
// String creation
let emptyString = ""
let anotherEmptyString = String()
// String interpolation
let name = "Alice"
let age = 30
let message = "My name is \(name) and I'm \(age) years old."
// Multi-line strings
let poem = """
Roses are red,
Violets are blue,
Swift is awesome,
And so are you!
"""
// String operations
let greeting = "Hello"
let world = "World"
let combined = greeting + ", " + world + "!"
// String properties and methods
let text = "Swift Programming"
print(text.count) // 17
print(text.isEmpty) // false
print(text.uppercased()) // SWIFT PROGRAMMING
print(text.lowercased()) // swift programming
print(text.hasPrefix("Swift")) // true
print(text.hasSuffix("ing")) // true
// String indexing
let str = "Hello"
let firstChar = str[str.startIndex] // H
let lastChar = str[str.index(before: str.endIndex)] // o
let secondChar = str[str.index(str.startIndex, offsetBy: 1)] // e
// Substring
let range = str.index(str.startIndex, offsetBy: 1)..<str.index(str.startIndex, offsetBy: 4)
let substring = str[range] // "ell"
```_
### Sammlungen Überblick
```swift
// Array
var numbers = [1, 2, 3, 4, 5]
var strings: [String] = ["apple", "banana", "cherry"]
var emptyArray: [Int] = []
// Set
var uniqueNumbers: Set<Int> = [1, 2, 3, 3, 4] // {1, 2, 3, 4}
var emptySet: Set<String> = []
// Dictionary
var ages = ["Alice": 30, "Bob": 25, "Charlie": 35]
var emptyDict: [String: Int] = [:]
// Tuple
let coordinates = (x: 10, y: 20)
let httpStatus = (404, "Not Found")
let person = (name: "John", age: 30, isEmployed: true)
```_
## Betreiber
### Arithmetische Operatoren
```swift
let a = 10
let b = 3
// Basic arithmetic
let sum = a + b // 13
let difference = a - b // 7
let product = a * b // 30
let quotient = a / b // 3
let remainder = a % b // 1
// Unary operators
let positive = +a // 10
let negative = -a // -10
// Compound assignment
var x = 5
x += 3 // x is now 8
x -= 2 // x is now 6
x *= 2 // x is now 12
x /= 3 // x is now 4
x %= 3 // x is now 1
```_
### Vergleich Betreiber
```swift
let a = 5
let b = 10
// Comparison
let isEqual = (a == b) // false
let isNotEqual = (a != b) // true
let isGreater = (a > b) // false
let isLess = (a < b) // true
let isGreaterOrEqual = (a >= b) // false
let isLessOrEqual = (a <= b) // true
// String comparison
let str1 = "apple"
let str2 = "banana"
let result = str1 < str2 // true (alphabetical order)
// Tuple comparison
let tuple1 = (1, "zebra")
let tuple2 = (2, "apple")
let tupleResult = tuple1 < tuple2 // true (compares first elements)
```_
### Logische Operatoren
```swift
let a = true
let b = false
// Logical NOT
let notA = !a // false
// Logical AND
let andResult = a && b // false
// Logical OR
let orResult = a || b // true
// Short-circuit evaluation
let result = a || expensiveFunction() // expensiveFunction() not called if a is true
```_
### Range Operatoren
```swift
// Closed range (includes both endpoints)
let closedRange = 1...5 // 1, 2, 3, 4, 5
// Half-open range (excludes upper bound)
let halfOpenRange = 1..<5 // 1, 2, 3, 4
// One-sided ranges
let oneSidedRange1 = 2... // 2 to end of collection
let oneSidedRange2 = ...2 // beginning to 2
let oneSidedRange3 = ..<2 // beginning to 2 (excluding 2)
// Using ranges
let numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
let subset = numbers[2...5] // [3, 4, 5, 6]
for i in 1...5 {
print(i) // Prints 1, 2, 3, 4, 5
}
```_
### Nil-Coalescing Operator
```swift
let optionalName: String? = nil
let defaultName = "Anonymous"
// Nil-coalescing operator
let name = optionalName ?? defaultName // "Anonymous"
// Equivalent to:
let name2 = optionalName != nil ? optionalName! : defaultName
// Chaining nil-coalescing
let a: String? = nil
let b: String? = nil
let c: String? = "Hello"
let result = a ?? b ?? c ?? "Default" // "Hello"
```_
## Steuerstrom
### Bedingte Aussagen
```swift
// if statement
let temperature = 25
if temperature > 30 {
print("It's hot!")
} else if temperature > 20 {
print("It's warm.")
} else {
print("It's cool.")
}
// Ternary operator
let message = temperature > 25 ? "Warm" : "Cool"
// guard statement
func processUser(name: String?) {
guard let userName = name, !userName.isEmpty else {
print("Invalid name")
return
}
print("Processing user: \(userName)")
}
// if let (optional binding)
let optionalNumber: Int? = 42
if let number = optionalNumber {
print("Number is \(number)")
} else {
print("Number is nil")
}
// Multiple optional binding
let optionalName: String? = "Alice"
let optionalAge: Int? = 30
if let name = optionalName, let age = optionalAge, age >= 18 {
print("\(name) is an adult")
}
```_
### Schaltaussagen
```swift
let character = "a"
switch character {
case "a", "e", "i", "o", "u":
print("Vowel")
case "b", "c", "d", "f", "g", "h", "j", "k", "l", "m", "n", "p", "q", "r", "s", "t", "v", "w", "x", "y", "z":
print("Consonant")
default:
print("Not a letter")
}
// Switch with ranges
let score = 85
switch score {
case 90...100:
print("A")
case 80..<90:
print("B")
case 70..<80:
print("C")
case 60..<70:
print("D")
default:
print("F")
}
// Switch with tuples
let point = (1, 1)
switch point {
case (0, 0):
print("Origin")
case (_, 0):
print("On x-axis")
case (0, _):
print("On y-axis")
case (-2...2, -2...2):
print("Inside the box")
default:
print("Outside the box")
}
// Switch with value binding
let anotherPoint = (2, 0)
switch anotherPoint {
case (let x, 0):
print("On x-axis at x = \(x)")
case (0, let y):
print("On y-axis at y = \(y)")
case let (x, y):
print("Point at (\(x), \(y))")
}
// Switch with where clause
let yetAnotherPoint = (1, -1)
switch yetAnotherPoint {
case let (x, y) where x == y:
print("On the line x == y")
case let (x, y) where x == -y:
print("On the line x == -y")
case let (x, y):
print("Point at (\(x), \(y))")
}
```_
### Loops
```swift
// for-in loop
let numbers = [1, 2, 3, 4, 5]
for number in numbers {
print(number)
}
// for-in with range
for i in 1...5 {
print("Count: \(i)")
}
// for-in with stride
for i in stride(from: 0, to: 10, by: 2) {
print(i) // 0, 2, 4, 6, 8
}
// for-in with enumerated
let fruits = ["apple", "banana", "cherry"]
for (index, fruit) in fruits.enumerated() {
print("\(index): \(fruit)")
}
// while loop
var count = 0
while count < 5 {
print("Count: \(count)")
count += 1
}
// repeat-while loop (do-while equivalent)
var number = 0
repeat {
print("Number: \(number)")
number += 1
} while number < 3
// Loop control
for i in 1...10 {
if i == 3 {
continue // Skip this iteration
}
if i == 8 {
break // Exit the loop
}
print(i)
}
// Labeled statements
outerLoop: for i in 1...3 {
innerLoop: for j in 1...3 {
if i == 2 && j == 2 {
break outerLoop
}
print("i: \(i), j: \(j)")
}
}
```_
## Funktionen
### Grundlegende Funktionen
```swift
// Simple function
func greet() {
print("Hello!")
}
greet()
// Function with parameters
func greet(name: String) {
print("Hello, \(name)!")
}
greet(name: "Alice")
// Function with return value
func add(a: Int, b: Int) -> Int {
return a + b
}
let sum = add(a: 5, b: 3)
// Function with multiple return values
func minMax(array: [Int]) -> (min: Int, max: Int) {
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)
}
let bounds = minMax(array: [8, -6, 2, 109, 3, 71])
print("Min: \(bounds.min), Max: \(bounds.max)")
```_
### Funktionsparameter
```swift
// External and internal parameter names
func greet(person name: String, from hometown: String) -> String {
return "Hello \(name)! Glad you could visit from \(hometown)."
}
print(greet(person: "Bill", from: "Cupertino"))
// Omitting external parameter names
func add(_ a: Int, _ b: Int) -> Int {
return a + b
}
let result = add(5, 3) // No parameter labels
// Default parameter values
func greet(name: String, greeting: String = "Hello") -> String {
return "\(greeting), \(name)!"
}
print(greet(name: "Alice")) // Uses default greeting
print(greet(name: "Bob", greeting: "Hi")) // Uses custom greeting
// Variadic parameters
func average(_ numbers: Double...) -> Double {
var total: Double = 0
for number in numbers {
total += number
}
return total / Double(numbers.count)
}
print(average(1, 2, 3, 4, 5)) // 3.0
// In-out parameters
func swapTwoInts(_ a: inout Int, _ b: inout Int) {
let temporaryA = a
a = b
b = temporaryA
}
var someInt = 3
var anotherInt = 107
swapTwoInts(&someInt, &anotherInt)
print("someInt: \(someInt), anotherInt: \(anotherInt)")
```_
### Funktionstypen
```swift
// Function as a type
func addTwoInts(_ a: Int, _ b: Int) -> Int {
return a + b
}
func multiplyTwoInts(_ a: Int, _ b: Int) -> Int {
return a * b
}
// Variable of function type
var mathFunction: (Int, Int) -> Int = addTwoInts
print(mathFunction(2, 3)) // 5
mathFunction = multiplyTwoInts
print(mathFunction(2, 3)) // 6
// Function as parameter
func printMathResult(_ mathFunction: (Int, Int) -> Int, _ a: Int, _ b: Int) {
print("Result: \(mathFunction(a, b))")
}
printMathResult(addTwoInts, 3, 5)
// Function as return type
func chooseStepFunction(backward: Bool) -> (Int) -> Int {
func stepForward(input: Int) -> Int { return input + 1 }
func stepBackward(input: Int) -> Int { return input - 1 }
return backward ? stepBackward : stepForward
}
let moveNearerToZero = chooseStepFunction(backward: true)
print(moveNearerToZero(5)) // 4
```_
### Eingebettete Funktionen
```swift
func chooseStepFunction(backward: Bool) -> (Int) -> Int {
func stepForward(input: Int) -> Int {
return input + 1
}
func stepBackward(input: Int) -> Int {
return input - 1
}
return backward ? stepBackward : stepForward
}
var currentValue = -4
let moveNearerToZero = chooseStepFunction(backward: currentValue > 0)
while currentValue != 0 {
print("\(currentValue)... ")
currentValue = moveNearerToZero(currentValue)
}
print("zero!")
```_
## Schließungen
### Basic Closures
```swift
// Closure expression syntax
let numbers = [1, 2, 3, 4, 5]
// Full closure syntax
let doubled = numbers.map({ (number: Int) -> Int in
return number * 2
})
// Inferring type from context
let doubled2 = numbers.map({ number in
return number * 2
})
// Implicit returns from single-expression closures
let doubled3 = numbers.map({ number in number * 2 })
// Shorthand argument names
let doubled4 = numbers.map({ $0 * 2 })
// Trailing closure syntax
let doubled5 = numbers.map { $0 * 2 }
// Multiple trailing closures
func loadPicture(from server: String, completion: (String) -> Void, onFailure: (String) -> Void) {
// Implementation
}
loadPicture(from: "server.com") { picture in
print("Loaded: \(picture)")
} onFailure: { error in
print("Failed: \(error)")
}
```_
### Werte erfassen
```swift
func makeIncrementer(forIncrement amount: Int) -> () -> Int {
var runningTotal = 0
func incrementer() -> Int {
runningTotal += amount
return runningTotal
}
return incrementer
}
let incrementByTen = makeIncrementer(forIncrement: 10)
print(incrementByTen()) // 10
print(incrementByTen()) // 20
print(incrementByTen()) // 30
let incrementBySeven = makeIncrementer(forIncrement: 7)
print(incrementBySeven()) // 7
print(incrementByTen()) // 40 (still independent)
```_
### Entschlackungen
```swift
var completionHandlers: [() -> Void] = []
func someFunctionWithEscapingClosure(completionHandler: @escaping () -> Void) {
completionHandlers.append(completionHandler)
}
func someFunctionWithNonescapingClosure(closure: () -> Void) {
closure() // Called before function returns
}
class SomeClass {
var x = 10
func doSomething() {
someFunctionWithEscapingClosure { self.x = 100 }
someFunctionWithNonescapingClosure { x = 200 }
}
}
let instance = SomeClass()
instance.doSomething()
print(instance.x) // 200
completionHandlers.first?()
print(instance.x) // 100
```_
### Autogehäuse
```swift
// Autoclosure delays evaluation
func serve(customer customerProvider: @autoclosure () -> String) {
print("Now serving \(customerProvider())!")
}
serve(customer: "Alex") // String is automatically wrapped in closure
// Autoclosure with escaping
var customerProviders: [() -> String] = []
func collectCustomerProviders(_ customerProvider: @autoclosure @escaping () -> String) {
customerProviders.append(customerProvider)
}
collectCustomerProviders("Barry")
collectCustomerProviders("Daniella")
print("Collected \(customerProviders.count) closures.")
for customerProvider in customerProviders {
print("Now serving \(customerProvider())!")
}
```_
## Klassen und Strukturen
### Grundprinzip
```swift
// Structure
struct Resolution {
var width = 0
var height = 0
// Computed property
var area: Int {
return width * height
}
// Method
mutating func scale(by factor: Int) {
width *= factor
height *= factor
}
}
// Class
class VideoMode {
var resolution = Resolution()
var interlaced = false
var frameRate = 0.0
var name: String?
// Initializer
init(name: String) {
self.name = name
}
// Method
func describe() -> String {
return "VideoMode: \(name ?? "Unknown")"
}
}
// Usage
var someResolution = Resolution(width: 1920, height: 1080)
print(someResolution.area) // 2073600
let someVideoMode = VideoMode(name: "HD")
someVideoMode.resolution = someResolution
someVideoMode.frameRate = 30.0
```_
### Initialisatoren
```swift
struct Celsius {
var temperatureInCelsius: Double
// Designated initializer
init(fromFahrenheit fahrenheit: Double) {
temperatureInCelsius = (fahrenheit - 32.0) / 1.8
}
init(fromKelvin kelvin: Double) {
temperatureInCelsius = kelvin - 273.15
}
// Default initializer
init(_ celsius: Double) {
temperatureInCelsius = celsius
}
}
let boilingPointOfWater = Celsius(fromFahrenheit: 212.0)
let freezingPointOfWater = Celsius(fromKelvin: 273.15)
let bodyTemperature = Celsius(37.0)
// Class initializers
class Person {
let name: String
var age: Int
// Designated initializer
init(name: String, age: Int) {
self.name = name
self.age = age
}
// Convenience initializer
convenience init(name: String) {
self.init(name: name, age: 0)
}
}
// Failable initializers
struct Animal {
let species: String
init?(species: String) {
if species.isEmpty {
return nil
}
self.species = species
}
}
let someCreature = Animal(species: "Giraffe")
if let giraffe = someCreature {
print("An animal was initialized with a species of \(giraffe.species)")
}
```_
### Wert vs Referenztypen
```swift
// Structures are value types
struct Point {
var x = 0.0, y = 0.0
}
var point1 = Point(x: 1.0, y: 2.0)
var point2 = point1 // Copy is made
point2.x = 3.0
print(point1.x) // 1.0 (unchanged)
print(point2.x) // 3.0
// Classes are reference types
class Size {
var width = 0.0, height = 0.0
}
let size1 = Size()
size1.width = 10.0
let size2 = size1 // Same reference
size2.width = 20.0
print(size1.width) // 20.0 (changed)
print(size2.width) // 20.0
// Identity operators for reference types
if size1 === size2 {
print("size1 and size2 refer to the same instance")
}
if size1 !== size2 {
print("size1 and size2 refer to different instances")
}
```_
## Eigenschaften
### Gespeicherte Eigenschaften
```swift
struct FixedLengthRange {
var firstValue: Int
let length: Int
// Lazy stored property
lazy var expensiveProperty: String = {
// Expensive computation
return "Computed value"
}()
}
var rangeOfThreeItems = FixedLengthRange(firstValue: 0, length: 3)
rangeOfThreeItems.firstValue = 6
// Property observers
class StepCounter {
var totalSteps: Int = 0 {
willSet(newTotalSteps) {
print("About to set totalSteps to \(newTotalSteps)")
}
didSet {
if totalSteps > oldValue {
print("Added \(totalSteps - oldValue) steps")
}
}
}
}
let stepCounter = StepCounter()
stepCounter.totalSteps = 200
stepCounter.totalSteps = 360
```_
### Computed Properties
```swift
struct Circle {
var radius: Double = 0.0
var area: Double {
get {
return Double.pi * radius * radius
}
set(newArea) {
radius = sqrt(newArea / Double.pi)
}
}
// Read-only computed property
var circumference: Double {
return 2.0 * Double.pi * radius
}
}
var circle = Circle(radius: 5.0)
print(circle.area) // 78.54
circle.area = 100.0
print(circle.radius) // 5.64
```_
### Produkte und Dienstleistungen
```swift
@propertyWrapper
struct TwelveOrLess {
private var number = 0
var wrappedValue: Int {
get { return number }
set { number = min(newValue, 12) }
}
}
struct SmallRectangle {
@TwelveOrLess var height: Int
@TwelveOrLess var width: Int
}
var rectangle = SmallRectangle()
print(rectangle.height) // 0
rectangle.height = 10
print(rectangle.height) // 10
rectangle.height = 24
print(rectangle.height) // 12
// Property wrapper with parameters
@propertyWrapper
struct SmallNumber {
private var maximum: Int
private var number: Int
var wrappedValue: Int {
get { return number }
set { number = min(newValue, maximum) }
}
init() {
maximum = 12
number = 0
}
init(wrappedValue: Int) {
maximum = 12
number = min(wrappedValue, maximum)
}
init(wrappedValue: Int, maximum: Int) {
self.maximum = maximum
number = min(wrappedValue, maximum)
}
}
struct UnitRectangle {
@SmallNumber var height: Int = 1
@SmallNumber var width: Int = 1
}
struct NarrowRectangle {
@SmallNumber(maximum: 5) var height: Int = 2
@SmallNumber(maximum: 4) var width: Int = 3
}
```_
### Typ Eigenschaften
```swift
struct SomeStructure {
static var storedTypeProperty = "Some value."
static var computedTypeProperty: Int {
return 1
}
}
enum SomeEnumeration {
static var storedTypeProperty = "Some value."
static var computedTypeProperty: Int {
return 6
}
}
class SomeClass {
static var storedTypeProperty = "Some value."
static var computedTypeProperty: Int {
return 27
}
class var overrideableComputedTypeProperty: Int {
return 107
}
}
print(SomeStructure.storedTypeProperty) // "Some value."
print(SomeEnumeration.computedTypeProperty) // 6
print(SomeClass.overrideableComputedTypeProperty) // 107
```_
## Methoden
### Verfahren
```swift
class Counter {
var count = 0
func increment() {
count += 1
}
func increment(by amount: Int) {
count += amount
}
func reset() {
count = 0
}
}
let counter = Counter()
counter.increment()
counter.increment(by: 5)
print(counter.count) // 6
counter.reset()
// Mutating methods for structures
struct Point {
var x = 0.0, y = 0.0
mutating func moveBy(x deltaX: Double, y deltaY: Double) {
x += deltaX
y += deltaY
}
mutating func moveToOrigin() {
self = Point(x: 0.0, y: 0.0)
}
}
var somePoint = Point(x: 1.0, y: 1.0)
somePoint.moveBy(x: 2.0, y: 3.0)
print("Point is now at (\(somePoint.x), \(somePoint.y))")
```_
### Typ Methoden
```swift
class SomeClass {
class func someTypeMethod() {
print("Type method called")
}
static func anotherTypeMethod() {
print("Static type method called")
}
}
SomeClass.someTypeMethod()
SomeClass.anotherTypeMethod()
struct LevelTracker {
static var highestUnlockedLevel = 1
var currentLevel = 1
static func unlock(_ level: Int) {
if level > highestUnlockedLevel {
highestUnlockedLevel = level
}
}
static func isUnlocked(_ level: Int) -> Bool {
return level <= highestUnlockedLevel
}
@discardableResult
mutating func advance(to level: Int) -> Bool {
if LevelTracker.isUnlocked(level) {
currentLevel = level
return true
} else {
return false
}
}
}
```_
## Erbschaft
### Grund Erbe
```swift
// Base class
class Vehicle {
var currentSpeed = 0.0
var description: String {
return "traveling at \(currentSpeed) miles per hour"
}
func makeNoise() {
// Do nothing - an arbitrary vehicle doesn't necessarily make a noise
}
}
// Subclass
class Bicycle: Vehicle {
var hasBasket = false
override var description: String {
return "Bicycle: \(super.description)"
}
}
class Tandem: Bicycle {
var currentNumberOfPassengers = 0
override var description: String {
return "Tandem: \(super.description) with \(currentNumberOfPassengers) passengers"
}
}
// Usage
let bicycle = Bicycle()
bicycle.hasBasket = true
bicycle.currentSpeed = 15.0
print(bicycle.description)
let tandem = Tandem()
tandem.currentSpeed = 22.0
tandem.currentNumberOfPassengers = 2
print(tandem.description)
```_
### Überschreiben
```swift
class Train: Vehicle {
override func makeNoise() {
print("Choo Choo")
}
override var currentSpeed: Double {
didSet {
print("Train speed changed to \(currentSpeed)")
}
}
}
class Car: Vehicle {
var gear = 1
override var description: String {
return super.description + " in gear \(gear)"
}
override func makeNoise() {
print("Vroom Vroom")
}
}
let train = Train()
train.makeNoise() // "Choo Choo"
let car = Car()
car.currentSpeed = 25.0
car.gear = 3
print(car.description) // "traveling at 25.0 miles per hour in gear 3"
```_
### Vermeidung von Overrides
```swift
class FinalVehicle {
final var maxSpeed = 100.0
final func startEngine() {
print("Engine started")
}
}
// This would cause a compile error:
// class FastCar: FinalVehicle {
// override func startEngine() { } // Error!
// }
// Final class cannot be subclassed
final class ImmutableClass {
let value = 42
}
// This would cause a compile error:
// class SubClass: ImmutableClass { } // Error!
```_
## Protokolle
### Grundprotokolle
```swift
protocol SomeProtocol {
var mustBeSettable: Int { get set }
var doesNotNeedToBeSettable: Int { get }
func someMethod()
static func someTypeMethod()
}
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 john = Person(fullName: "John Appleseed")
let ncc1701 = Starship(name: "Enterprise", prefix: "USS")
```_
### Verfahrensvorschriften
```swift
protocol Togglable {
mutating func toggle()
}
enum OnOffSwitch: Togglable {
case off, on
mutating func toggle() {
switch self {
case .off:
self = .on
case .on:
self = .off
}
}
}
var lightSwitch = OnOffSwitch.off
lightSwitch.toggle() // lightSwitch is now .on
```_
### Protokoll Erbschaft
```swift
protocol InheritingProtocol: SomeProtocol {
func anotherMethod()
}
protocol PrettyTextRepresentable: CustomStringConvertible {
var prettyTextualDescription: String { get }
}
extension Person: PrettyTextRepresentable {
var description: String {
return fullName
}
var prettyTextualDescription: String {
return "Person: \(fullName)"
}
}
```_
### Nur Protokolle
```swift
protocol SomeClassOnlyProtocol: AnyObject {
func someMethod()
}
class SomeClass: SomeClassOnlyProtocol {
func someMethod() {
print("Method implemented")
}
}
// This would cause an error:
// struct SomeStruct: SomeClassOnlyProtocol { } // Error!
```_
### Protokollzusammensetzung
```swift
protocol Named {
var name: String { get }
}
protocol Aged {
var age: Int { get }
}
struct PersonStruct: Named, Aged {
var name: String
var age: Int
}
func wishHappyBirthday(to celebrator: Named & Aged) {
print("Happy birthday, \(celebrator.name), you're \(celebrator.age)!")
}
let birthdayPerson = PersonStruct(name: "Malcolm", age: 21)
wishHappyBirthday(to: birthdayPerson)
```_
### Optionale Protokollvoraussetzungen
```swift
@objc protocol CounterDataSource {
@objc optional func increment(forCount count: Int) -> Int
@objc optional var fixedIncrement: Int { get }
}
class Counter {
var count = 0
var dataSource: CounterDataSource?
func increment() {
if let amount = dataSource?.increment?(forCount: count) {
count += amount
} else if let amount = dataSource?.fixedIncrement {
count += amount
}
}
}
```_
### Protokollerweiterungen
```swift
extension Collection {
var isNotEmpty: Bool {
return !isEmpty
}
}
let numbers = [1, 2, 3]
print(numbers.isNotEmpty) // true
// Protocol extension with constraints
extension Collection where Element: Equatable {
func allEqual() -> Bool {
for element in self {
if element != self.first {
return false
}
}
return true
}
}
let equalNumbers = [1, 1, 1]
print(equalNumbers.allEqual()) // true
```_
## Erweiterungen
### Basiserweiterungen
```swift
extension Double {
var km: Double { return self * 1_000.0 }
var m: Double { return self }
var cm: Double { return self / 100.0 }
var mm: Double { return self / 1_000.0 }
var ft: Double { return self / 3.28084 }
}
let oneInch = 25.4.mm
print("One inch is \(oneInch) meters") // 0.0254 meters
let threeFeet = 3.ft
print("Three feet is \(threeFeet) meters") // 0.914399970739201 meters
```_
### Methoden hinzufügen
```swift
extension Int {
func repetitions(task: () -> Void) {
for _ in 0..<self {
task()
}
}
mutating func square() {
self = self * self
}
}
3.repetitions {
print("Hello!")
}
var someInt = 3
someInt.square() // someInt is now 9
```_
### Hinzufügen von Initializern
```swift
struct Size {
var width = 0.0, height = 0.0
}
struct Point {
var x = 0.0, y = 0.0
}
struct Rect {
var origin = Point()
var size = Size()
}
extension Rect {
init(center: Point, size: Size) {
let originX = center.x - (size.width / 2)
let originY = center.y - (size.height / 2)
self.init(origin: Point(x: originX, y: originY), size: size)
}
}
let centerRect = Rect(center: Point(x: 4.0, y: 4.0), size: Size(width: 3.0, height: 3.0))
```_
### Hinzufügen von Subskripten
```swift
extension Int {
subscript(digitIndex: Int) -> Int {
var decimalBase = 1
for _ in 0..<digitIndex {
decimalBase *= 10
}
return (self / decimalBase) % 10
}
}
746381295[0] // 5
746381295[1] // 9
746381295[2] // 2
746381295[8] // 7
```_
### Eingebettete Arten hinzufügen
```swift
extension Int {
enum Kind {
case negative, zero, positive
}
var kind: Kind {
switch self {
case 0:
return .zero
case let x where x > 0:
return .positive
default:
return .negative
}
}
}
func printIntegerKinds(_ numbers: [Int]) {
for number in numbers {
switch number.kind {
case .negative:
print("- ", terminator: "")
case .zero:
print("0 ", terminator: "")
case .positive:
print("+ ", terminator: "")
}
}
print("")
}
printIntegerKinds([3, 19, -27, 0, -6, 0, 7]) // + + - 0 - 0 +
```_
## Generics
### Generische Funktionen
```swift
func swapTwoValues<T>(_ a: inout T, _ b: inout T) {
let temporaryA = a
a = b
b = temporaryA
}
var someInt = 3
var anotherInt = 107
swapTwoValues(&someInt, &anotherInt)
print("someInt: \(someInt), anotherInt: \(anotherInt)")
var someString = "hello"
var anotherString = "world"
swapTwoValues(&someString, &anotherString)
print("someString: \(someString), anotherString: \(anotherString)")
```_
### Generische Typen
```swift
struct Stack<Element> {
var items: [Element] = []
mutating func push(_ item: Element) {
items.append(item)
}
mutating func pop() -> Element {
return items.removeLast()
}
var isEmpty: Bool {
return items.isEmpty
}
var count: Int {
return items.count
}
}
var stackOfStrings = Stack<String>()
stackOfStrings.push("uno")
stackOfStrings.push("dos")
stackOfStrings.push("tres")
stackOfStrings.push("cuatro")
let fromTheTop = stackOfStrings.pop() // "cuatro"
```_
### Typ Constraints
```swift
func findIndex<T: Equatable>(of valueToFind: T, in array: [T]) -> Int? {
for (index, value) in array.enumerated() {
if value == valueToFind {
return index
}
}
return nil
}
let doubleIndex = findIndex(of: 9.3, in: [3.14159, 0.1, 0.25])
let stringIndex = findIndex(of: "Andrea", in: ["Mike", "Malcolm", "Andrea"])
// Generic type with multiple constraints
func allItemsMatch<C1: Container, C2: Container>(_ someContainer: C1, _ anotherContainer: C2) -> Bool
where C1.Item == C2.Item, C1.Item: Equatable {
if someContainer.count != anotherContainer.count {
return false
}
for i in 0..<someContainer.count {
if someContainer[i] != anotherContainer[i] {
return false
}
}
return true
}
```_
### assoziierte Typen
```swift
protocol Container {
associatedtype Item
mutating func append(_ item: Item)
var count: Int { get }
subscript(i: Int) -> Item { get }
}
struct IntStack: Container {
var items: [Int] = []
mutating func push(_ item: Int) {
items.append(item)
}
mutating func pop() -> Int {
return items.removeLast()
}
// Container protocol conformance
typealias Item = Int
mutating func append(_ item: Int) {
self.push(item)
}
var count: Int {
return items.count
}
subscript(i: Int) -> Int {
return items[i]
}
}
extension Stack: Container {
// No need to declare typealias Item = Element
// Swift can infer that Element is the appropriate type for Item
mutating func append(_ item: Element) {
self.push(item)
}
subscript(i: Int) -> Element {
return items[i]
}
}
```_
### Generika Wo Klauseln
```swift
func allItemsMatch<C1: Container, C2: Container>(_ someContainer: C1, _ anotherContainer: C2) -> Bool
where C1.Item == C2.Item, C1.Item: Equatable {
if someContainer.count != anotherContainer.count {
return false
}
for i in 0..<someContainer.count {
if someContainer[i] != anotherContainer[i] {
return false
}
}
return true
}
// Extensions with generic where clauses
extension Stack where Element: Equatable {
func isTop(_ item: Element) -> Bool {
guard let topItem = items.last else {
return false
}
return topItem == item
}
}
extension Container where Item: Equatable {
func startsWith(_ item: Item) -> Bool {
return count >= 1 && self[0] == item
}
}
extension Container where Item == Double {
func average() -> Double {
var sum = 0.0
for index in 0..<count {
sum += self[index]
}
return sum / Double(count)
}
}
```_
## Fehlerbehebung
### Fehler definieren
```swift
enum VendingMachineError: Error {
case invalidSelection
case insufficientFunds(coinsNeeded: Int)
case outOfStock
}
// Custom error with localized description
struct ValidationError: Error, LocalizedError {
let message: String
var errorDescription: String? {
return message
}
}
```_
### Wurffunktionen
```swift
func canThrowErrors() throws -> String {
// Function implementation
return "Success"
}
func cannotThrowErrors() -> String {
// Function implementation
return "Success"
}
struct Item {
var price: Int
var count: Int
}
class VendingMachine {
var inventory = [
"Candy Bar": Item(price: 12, count: 7),
"Chips": Item(price: 10, count: 4),
"Pretzels": Item(price: 7, count: 11)
]
var coinsDeposited = 0
func vend(itemNamed name: String) throws {
guard let item = inventory[name] else {
throw VendingMachineError.invalidSelection
}
guard item.count > 0 else {
throw VendingMachineError.outOfStock
}
guard item.price <= coinsDeposited else {
throw VendingMachineError.insufficientFunds(coinsNeeded: item.price - coinsDeposited)
}
coinsDeposited -= item.price
var newItem = item
newItem.count -= 1
inventory[name] = newItem
print("Dispensing \(name)")
}
}
```_
### Umgang mit Fehlern
```swift
let vendingMachine = VendingMachine()
vendingMachine.coinsDeposited = 8
// do-catch
do {
try vendingMachine.vend(itemNamed: "Candy Bar")
} catch VendingMachineError.invalidSelection {
print("Invalid Selection.")
} catch VendingMachineError.outOfStock {
print("Out of Stock.")
} catch VendingMachineError.insufficientFunds(let coinsNeeded) {
print("Insufficient funds. Please insert an additional \(coinsNeeded) coins.")
} catch {
print("Unexpected error: \(error).")
}
// Multiple catch patterns
do {
try vendingMachine.vend(itemNamed: "Candy Bar")
} catch VendingMachineError.invalidSelection, VendingMachineError.insufficientFunds {
print("Invalid selection or insufficient funds.")
} catch {
print("Other error: \(error)")
}
// Converting errors to optional values
func someThrowingFunction() throws -> Int {
return 42
}
let x = try? someThrowingFunction()
// x is of type Int? and equals 42
let y: Int?
do {
y = try someThrowingFunction()
} catch {
y = nil
}
// Disabling error propagation
let z = try! someThrowingFunction()
// If someThrowingFunction() throws an error, you'll get a runtime error
```_
### Defer Statements
```swift
func processFile(filename: String) throws {
let file = openFile(named: filename)
defer {
closeFile(file)
}
// Work with the file
if someCondition {
return // closeFile(file) is called here
}
if anotherCondition {
throw SomeError.errorCondition // closeFile(file) is called here too
}
// closeFile(file) is called here as well
}
// Multiple defer statements
func deferExample() {
defer { print("First defer") }
defer { print("Second defer") }
defer { print("Third defer") }
print("End of function")
}
// Output:
// End of function
// Third defer
// Second defer
// First defer
```_
### Ergebnistyp
```swift
enum NetworkError: Error {
case badURL
case requestFailed
case unknown
}
func fetchData(from urlString: String) -> Result<Data, NetworkError> {
guard let url = URL(string: urlString) else {
return .failure(.badURL)
}
// Simulate network request
let success = Bool.random()
if success {
return .success(Data())
} else {
return .failure(.requestFailed)
}
}
// Using Result
let result = fetchData(from: "https://example.com")
switch result {
case .success(let data):
print("Received data: \(data)")
case .failure(let error):
print("Error: \(error)")
}
// Result with map and flatMap
let transformedResult = result
.map { data in
return String(data: data, encoding: .utf8) ?? ""
}
.mapError { error in
return "Network error: \(error)"
}
```_
## Speicherverwaltung
### Automatische Referenzzählung (ARC)
```swift
class Person {
let name: String
init(name: String) {
self.name = name
print("\(name) is being initialized")
}
deinit {
print("\(name) is being deinitialized")
}
}
var reference1: Person?
var reference2: Person?
var reference3: Person?
reference1 = Person(name: "John Appleseed")
// Prints "John Appleseed is being initialized"
reference2 = reference1
reference3 = reference1
// Strong reference count is now 3
reference1 = nil
reference2 = nil
// Strong reference count is now 1
reference3 = nil
// Strong reference count is now 0
// Prints "John Appleseed is being deinitialized"
Starke Referenzzyklen¶
```swift class Person { let name: String init(name: String) { self.name = name } var apartment: Apartment? deinit { print("(name) is being deinitialized") } }
class Apartment { let unit: String init(unit: String) { self.unit = unit } var tenant: Person? deinit { print("Apartment (unit) is being deinitialized") } }
var john: Person? var unit4A: Apartment?
john = Person(name: "John Appleseed") unit4A = Apartment(unit: "4A")
john!.apartment = unit4A unit4A!.tenant = john
john = nil unit4A = nil // Neither deinitializer is called - memory leak! ```_
Schwache Referenzen¶
```swift class Person { let name: String init(name: String) { self.name = name } var apartment: Apartment? deinit { print("(name) is being deinitialized") } }
class Apartment { let unit: String init(unit: String) { self.unit = unit } weak var tenant: Person? // Weak reference deinit { print("Apartment (unit) is being deinitialized") } }
var john: Person? var unit4A: Apartment?
john = Person(name: "John Appleseed") unit4A = Apartment(unit: "4A")
john!.apartment = unit4A unit4A!.tenant = john
john = nil // Prints "John Appleseed is being deinitialized"
print(unit4A!.tenant) // nil
unit4A = nil // Prints "Apartment 4A is being deinitialized" ```_
Unbekannte Referenzen¶
```swift class Customer { let name: String var card: CreditCard? init(name: String) { self.name = name } deinit { print("(name) is being deinitialized") } }
class CreditCard { let number: UInt64 unowned let customer: Customer // Unowned reference init(number: UInt64, customer: Customer) { self.number = number self.customer = customer } deinit { print("Card #(number) is being deinitialized") } }
var john: Customer? john = Customer(name: "John Appleseed") john!.card = CreditCard(number: 1234_5678_9012_3456, customer: john!)
john = nil // Prints "John Appleseed is being deinitialized" // Prints "Card #1234567890123456 is being deinitialized" ```_
Schließungen und starke Referenzzyklen¶
```swift class HTMLElement { let name: String let text: String?
lazy var asHTML: () -> String = { [unowned self] in
if let text = self.text {
return "<\(self.name)>\(text)</\(self.name)>"
} else {
return "<\(self.name) />"
}
}
init(name: String, text: String? = nil) {
self.name = name
self.text = text
}
deinit {
print("\(name) is being deinitialized")
}
}
var paragraph: HTMLElement? = HTMLElement(name: "p", text: "hello, world") print(paragraph!.asHTML())
paragraph = nil // Prints "p is being deinitialized"
// Capture list with weak reference class SomeClass { var value = 0
func doSomething() {
let closure = { [weak self] in
guard let self = self else { return }
print("Value: \(self.value)")
}
closure()
}
} ```_
Konkurs¶
Async/Await (iOS 15+)¶
```swift // Async function func fetchUserID(from server: String) async -> Int { let userID = 501 return userID }
func fetchUsername(from server: String) async -> String { let username = "Taylor" return username }
// Calling async functions func connectUser(to server: String) async { async let userID = fetchUserID(from: server) async let username = fetchUsername(from: server)
let greeting = await "Hello \(username), user ID \(userID)"
print(greeting)
}
// Async sequence func fetchData() async throws -> [String] { // Simulate network delay try await Task.sleep(nanoseconds: 1_000_000_000) return ["Item 1", "Item 2", "Item 3"] }
// Using async in SwiftUI struct ContentView: View { @State private var data: [String] = []
var body: some View {
List(data, id: \.self) { item in
Text(item)
}
.task {
do {
data = try await fetchData()
} catch {
print("Failed to fetch data: \(error)")
}
}
}
} ```_
Aufgaben¶
```swift // Creating tasks func performWork() async { let task1 = Task { return await fetchUserID(from: "server1") }
let task2 = Task {
return await fetchUsername(from: "server2")
}
let userID = await task1.value
let username = await task2.value
print("User: \(username) (\(userID))")
}
// Task cancellation func cancellableWork() async { let task = Task { for i in 1...10 { if Task.isCancelled { print("Task was cancelled") return } print("Working on step (i)") try await Task.sleep(nanoseconds: 1_000_000_000) } }
// Cancel after 3 seconds
DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
task.cancel()
}
await task.value
}
// Task groups func fetchMultipleUsers() async -> [String] { await withTaskGroup(of: String.self) { group in let servers = ["server1", "server2", "server3"]
for server in servers {
group.addTask {
return await fetchUsername(from: server)
}
}
var usernames: [String] = []
for await username in group {
usernames.append(username)
}
return usernames
}
} ```_
Rechtsakte¶
```swift actor BankAccount { private var balance: Double
init(initialBalance: Double) {
balance = initialBalance
}
func deposit(amount: Double) {
balance += amount
}
func withdraw(amount: Double) -> Bool {
if balance >= amount {
balance -= amount
return true
}
return false
}
func getBalance() -> Double {
return balance
}
}
// Using actors func bankingExample() async { let account = BankAccount(initialBalance: 1000)
await account.deposit(amount: 500)
let success = await account.withdraw(amount: 200)
let balance = await account.getBalance()
print("Withdrawal successful: \(success), Balance: \(balance)")
}
// MainActor for UI updates @MainActor class ViewModel: ObservableObject { @Published var data: [String] = []
func loadData() async {
let newData = await fetchDataFromNetwork()
// This runs on the main actor automatically
self.data = newData
}
}
func fetchDataFromNetwork() async -> [String] { // Network operation return ["Data 1", "Data 2", "Data 3"] } ```_
AsyncSequenz¶
```swift // Custom AsyncSequence struct Counter: AsyncSequence { typealias Element = Int
let howHigh: Int
struct AsyncIterator: AsyncIteratorProtocol {
let howHigh: Int
var current = 1
mutating func next() async -> Int? {
guard current <= howHigh else {
return nil
}
let result = current
current += 1
return result
}
}
func makeAsyncIterator() -> AsyncIterator {
return AsyncIterator(howHigh: howHigh)
}
}
// Using AsyncSequence func useAsyncSequence() async { for await number in Counter(howHigh: 5) { print(number) } }
// Built-in AsyncSequence operations func processAsyncData() async { let numbers = Counter(howHigh: 10)
let evenNumbers = numbers.filter { $0 % 2 == 0 }
let doubled = evenNumbers.map { $0 * 2 }
for await number in doubled {
print("Even doubled: \(number)")
}
} ```_
Sammlungen¶
Arrays¶
```swift // Array creation var someInts: [Int] = [] var threeDoubles = Array(repeating: 0.0, count: 3) var anotherThreeDoubles = Array(repeating: 2.5, count: 3) var sixDoubles = threeDoubles + anotherThreeDoubles
// Array literals var shoppingList: [String] = ["Eggs", "Milk"] var shoppingList2 = ["Eggs", "Milk"] // Type inferred
// Array operations shoppingList.append("Flour") shoppingList += ["Baking Powder"] shoppingList += ["Chocolate Spread", "Cheese", "Butter"]
let firstItem = shoppingList[0] shoppingList[0] = "Six eggs" shoppingList[4...6] = ["Bananas", "Apples"]
shoppingList.insert("Maple Syrup", at: 0) let mapleSyrup = shoppingList.remove(at: 0) let apples = shoppingList.removeLast()
// Array iteration for item in shoppingList { print(item) }
for (index, value) in shoppingList.enumerated() { print("Item (index + 1): (value)") }
// Array methods let numbers = [1, 2, 3, 4, 5] let doubled = numbers.map { $0 * 2 } let evens = numbers.filter { $0 % 2 == 0 } let sum = numbers.reduce(0, +) let first = numbers.first let last = numbers.last let contains = numbers.contains(3) ```_
Sets¶
```swift
// Set creation
var letters = Set
// Set operations favoriteGenres.insert("Jazz") if let removedGenre = favoriteGenres.remove("Rock") { print("(removedGenre)? I'm over it.") } else { print("I never much cared for that.") }
if favoriteGenres.contains("Funk") { print("I get up on the good foot.") } else { print("It's too funky in here.") }
// Set iteration for genre in favoriteGenres { print("(genre)") }
for genre in favoriteGenres.sorted() { print("(genre)") }
// Set operations let oddDigits: Set = [1, 3, 5, 7, 9] let evenDigits: Set = [0, 2, 4, 6, 8] let singleDigitPrimeNumbers: Set = [2, 3, 5, 7]
let union = oddDigits.union(evenDigits).sorted() let intersection = oddDigits.intersection(evenDigits).sorted() let subtracting = oddDigits.subtracting(singleDigitPrimeNumbers).sorted() let symmetricDifference = oddDigits.symmetricDifference(singleDigitPrimeNumbers).sorted()
// Set membership and equality let houseAnimals: Set = ["🐶", "🐱"] let farmAnimals: Set = ["🐮", "🐔", "🐑", "🐶", "🐱"] let cityAnimals: Set = ["🐦", "🐭"]
houseAnimals.isSubset(of: farmAnimals) // true farmAnimals.isSuperset(of: houseAnimals) // true farmAnimals.isDisjoint(with: cityAnimals) // true ```_
Tagebuch¶
```swift // Dictionary creation var namesOfIntegers: [Int: String] = [:] var airports: [String: String] = ["YYZ": "Toronto Pearson", "DUB": "Dublin"] var airports2 = ["YYZ": "Toronto Pearson", "DUB": "Dublin"]
// Dictionary operations airports["LHR"] = "London" airports["LHR"] = "London Heathrow"
if let oldValue = airports.updateValue("Dublin Airport", forKey: "DUB") { print("The old value for DUB was (oldValue).") }
if let airportName = airports["DUB"] { print("The name of the airport is (airportName).") } else { print("That airport is not in the airports dictionary.") }
airports["APL"] = "Apple International" airports["APL"] = nil
if let removedValue = airports.removeValue(forKey: "DUB") { print("The removed airport's name is (removedValue).") } else { print("The airports dictionary does not contain a value for DUB.") }
// Dictionary iteration for (airportCode, airportName) in airports { print("(airportCode): (airportName)") }
for airportCode in airports.keys { print("Airport code: (airportCode)") }
for airportName in airports.values { print("Airport name: (airportName)") }
let airportCodes = String let airportNames = String ```_
Optional¶
Optionale Grundlagen¶
```swift // Optional declaration var optionalString: String? = "Hello" var optionalInt: Int? = nil
// Optional binding if let actualString = optionalString { print("The string is (actualString)") } else { print("The string is nil") }
// Multiple optional binding if let string = optionalString, let int = optionalInt { print("Both values exist: (string), (int)") }
// Guard statement func processOptional(_ value: String?) { guard let unwrappedValue = value else { print("Value is nil") return } print("Processing: (unwrappedValue)") }
// Nil coalescing operator let defaultName = "Anonymous" let username = optionalString ?? defaultName
// 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).") } ```_
Implizit Unwrapped Optionals¶
```swift let possibleString: String? = "An optional string." let forcedString: String = possibleString! // Requires an exclamation point
let assumedString: String! = "An implicitly unwrapped optional string." let implicitString: String = assumedString // No need for an exclamation point
// Still can be treated as optional if assumedString != nil { print(assumedString!) }
if let definiteString = assumedString { print(definiteString) } ```_
Optionale Karte und FlatMap¶
```swift let possibleNumber = "123" let convertedNumber = Int(possibleNumber)
// Optional map let doubled = convertedNumber.map { $0 * 2 } print(doubled) // Optional(246)
// Optional flatMap func doubleIfEven(_ number: Int) -> Int? { return number % 2 == 0 ? number * 2 : nil }
let result = convertedNumber.flatMap(doubleIfEven) print(result) // nil (because 123 is odd)
// Chaining optionals let numbers = ["1", "2", "three", "4"] let validNumbers = numbers.compactMap { Int($0) } print(validNumbers) // [1, 2, 4] ```_
Best Practices¶
Code Style¶
```swift // Use meaningful names var userAge = 25 // Good var a = 25 // Bad
func calculateTotalPrice() -> Double // Good func calc() -> Double // Bad
// Use type inference when possible let name = "John" // Good let name: String = "John" // Unnecessary
// Use guard for early returns func processUser(_ user: User?) { guard let user = user else { return } guard user.isActive else { return }
// Process user
}
// Use trailing closures numbers.map { $0 * 2 } // Good numbers.map({ $0 * 2 }) // Less preferred
// Use computed properties for simple calculations struct Circle { var radius: Double
var area: Double { // Good
return .pi * radius * radius
}
func getArea() -> Double { // Less preferred
return .pi * radius * radius
}
} ```_
Leistung¶
```swift // Use lazy properties for expensive computations class DataProcessor { lazy var expensiveData: [String] = { // Expensive computation return processLargeDataSet() }()
private func processLargeDataSet() -> [String] {
// Implementation
return []
}
}
// Use value types when possible struct Point { // Good - value type var x: Double var y: Double }
class PointClass { // Use only when reference semantics needed var x: Double var y: Double
init(x: Double, y: Double) {
self.x = x
self.y = y
}
}
// Use copy-on-write for large value types struct LargeDataStructure { private var _data: NSMutableArray
private var data: NSMutableArray {
mutating get {
if !isKnownUniquelyReferenced(&_data) {
_data = _data.mutableCopy() as! NSMutableArray
}
return _data
}
}
init() {
_data = NSMutableArray()
}
} ```_
Fehlerbehebung¶
```swift // Use specific error types enum ValidationError: Error { case emptyInput case invalidFormat case tooShort(minimumLength: Int) case tooLong(maximumLength: Int) }
// Provide meaningful error messages extension ValidationError: LocalizedError { var errorDescription: String? { switch self { case .emptyInput: return "Input cannot be empty" case .invalidFormat: return "Input format is invalid" case .tooShort(let minimumLength): return "Input must be at least (minimumLength) characters" case .tooLong(let maximumLength): return "Input cannot exceed (maximumLength) characters" } } }
// Use Result type for better error handling
func validateInput(_ input: String) -> Result
guard input.count >= 3 else {
return .failure(.tooShort(minimumLength: 3))
}
return .success(input)
} ```_
Speicherverwaltung¶
```swift // Use weak references to avoid retain cycles class Parent { var children: [Child] = []
func addChild(_ child: Child) {
child.parent = self
children.append(child)
}
}
class Child { weak var parent: Parent? }
// Use capture lists in closures class ViewController { var completion: (() -> Void)?
func setupCompletion() {
completion = { [weak self] in
self?.dismiss()
}
}
func dismiss() {
// Implementation
}
}
// Use unowned when reference will never be nil class Customer { let name: String var card: CreditCard?
init(name: String) {
self.name = name
}
}
class CreditCard { let number: UInt64 unowned let customer: Customer
init(number: UInt64, customer: Customer) {
self.number = number
self.customer = customer
}
} ```_
--
Zusammenfassung¶
Swift ist eine leistungsstarke, moderne Programmiersprache für Sicherheit, Leistung und Ausdruckskraft. Zu den wichtigsten Merkmalen gehören:
- Typ Sicherheit: Starkes Typsystem verhindert viele gemeinsame Programmierfehler
- Memory Safety: Automatische Referenzzählung (ARC) verwaltet den Speicher automatisch
- Leistung: Fertige Sprache mit Geschwindigkeitsoptimierungen
- Expressivität: Saubere, lesbare Syntax, die leicht zu lernen und zu pflegen ist
- Interoperabilität: Nahtlose Integration mit Ziel-C- und C-Bibliotheken
- Moderne Features: Optionale, Generika, Schließungen und protokollorientierte Programmierung
- Konkurrenz: Eingebautes Async/Erwartungs- und Aktormodell für sichere gleichzeitige Programmierung
- Open Source: Verfügbar auf mehreren Plattformen über das Ökosystem von Apple
Swift kombiniert die Leistung und Effizienz der kompilierten Sprachen mit der Einfachheit und Interaktivität der populären Skriptsprachen, so dass es eine ausgezeichnete Wahl für iOS, macOS, watchOS, tvOS und serverseitige Entwicklung.
<= <= <= <================================================================================= Funktion copyToClipboard() {\cHFFFF} const commands = document.querySelectorAll('code'); alle Befehle = ''; Befehle. Für jede(cmd) => alle Befehle += cmd.textContent + '\n'); navigator.clipboard.writeText (allCommands); Alarm ('Alle Befehle, die in die Zwischenablage kopiert werden!'); }
Funktion generierenPDF() { Fenster.print(); }