Saltar a contenido

Swift Cheatsheet

יh1⁄4] Confía en el potencial y la programación intuitiva de Apple Idioma seleccionado/h1 "Clase de inscripción" Swift es un lenguaje de programación potente e intuitivo para iOS, macOS, watchOS y tvOS. Escribir código Swift es interactivo y divertido, la sintaxis es concisa pero expresiva, y Swift incluye características modernas amor de los desarrolladores. ▪/p] ■/div titulada

########################################################################################################################################################################################################################################################## Copiar todos los comandos
########################################################################################################################################################################################################################################################## Generar PDF seleccionado/button

■/div titulada ■/div titulada

Cuadro de contenidos

Instalación

Instalación de código X

# 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 en Linux

# 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

Sintaxis básica

Hola Mundo

// 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)!"
}

Semicolons and Line Breaks

// 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

Variables y Constantes

Declaración

// 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"
}

Naming Conventions

// 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

Tipos de datos

Tipos básicos

// 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

Manipulación de cuerdas

// 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"

Resumen de las colecciones

// 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)

Operadores

Operadores Aritméticos

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

Operadores de comparación

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)

Operadores lógicos

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

Operadores de rango

// 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

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"

Flujo de control

Declaraciones condicionales

// 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")
}

Interruptor de declaraciones

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

// 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)")
    }
}

Funciones

Funciones básicas

// 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)")

Parámetros de función

// 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)")

Tipos de función

// 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

Funciones anidadas

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!")

Cierre

Cierre básico

// 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)")
}

Valores de captura

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)

Escaping Closures

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

Autoclosures

// 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())!")
}

Clases y estructuras

Sintaxis básica

// 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

Iniciadores

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)")
}

Valor vs Tipos de referencia

// 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")
}

Propiedades

Propiedades almacenadas

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

Propiedades calculadas

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

Violadores de bienes

@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
}

Tipo

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

Métodos

Métodos de instalación

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))")

Tipo Métodos

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
        }
    }
}

Herencia

Herencia básica

// 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)

Arreglo

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"

Preventing Overrides

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!

Protocolos

Protocolos básicos

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")

Métodos necesarios

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

Protocolo

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)"
    }
}

Protocolos sólo de clase

protocol SomeClassOnlyProtocol: AnyObject {
    func someMethod()
}

class SomeClass: SomeClassOnlyProtocol {
    func someMethod() {
        print("Method implemented")
    }
}

// This would cause an error:
// struct SomeStruct: SomeClassOnlyProtocol { } // Error!

Protocol Composition

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)

Necesidades del Protocolo Facultativo

@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
        }
    }
}
```_

### Extensiones de Protocolo
```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

Extensiones

Extensiones básicas

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

Agregar métodos

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

Añadiendo inicializadores

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))

Añadiendo subscriptos

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
```_

### Agregar tipos anidados
```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 +

Genéricos

Funciones genéricas

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)")

Tipos genéricos

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"

Tipo Constraints

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
}

Tipos asociados

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]
    }
}

Genérico Donde Cláusulas

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)
    }
}

Manejo de errores

Definir errores

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
    }
}

Funciones de lanzamiento

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)")
    }
}

Manejo de errores

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

Declaraciones de aplazamiento

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

Tipo de resultado

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)"
    }

Gestión de memoria

Conteo automático de referencia (ARC)

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"

Ciclos de referencia fuertes

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!

Referencias débiles

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"

Referencias no propiedad

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"

Ciclos de cierre y ciclos de referencia fuertes

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()
    }
}

Concurrencia

Async/Await (iOS 15+)

// 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)")
            }
        }
    }
}

Tareas

// 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
    }
}
```_

### Actores
```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"]
}

AsyncSequence

// 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)")
    }
}

Colecciones

Arrays

// 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

// Set creation
var letters = Set<Character>()
var favoriteGenres: Set<String> = ["Rock", "Classical", "Hip hop"]

// 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

Diccionarios

// 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](airports.keys)
let airportNames = [String](airports.values)

Facultativos

Fundamentos opcionales

// 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).")
}

Opcionales implícitamente desenfundados

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)
}

Mapa opcional y FlatMap

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]

Buenas prácticas

Code Style

// 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
    }
}

Ejecución

// 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()
    }
}

Manejo de errores

// 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<String, ValidationError> {
    guard !input.isEmpty else {
        return .failure(.emptyInput)
    }

    guard input.count >= 3 else {
        return .failure(.tooShort(minimumLength: 3))
    }

    return .success(input)
}

Gestión de memoria

// 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
    }
}

-...

Resumen

Swift es un lenguaje de programación potente y moderno diseñado para la seguridad, el rendimiento y la expresividad. Las características principales incluyen:

  • ** Seguridad del tipo**: El sistema de tipo fuerte previene muchos errores comunes de programación
  • ** Seguridad de memoria**: Conteo automático de referencia (ARC) administra la memoria automáticamente
  • Performance: Lenguaje compilado con optimizaciones para velocidad
  • Expresividad: Sintaxis limpia y legible que es fácil de aprender y mantener
  • Interoperabilidad: Integración sin costuras con bibliotecas Objetivo-C y C
  • Características modernas: Opcionales, genéricos, cierres y programación orientada al protocolo
  • Concurrencia: Modelo integrado de asinc/await y actor para una programación concurrente segura
  • Open Source: Disponible en múltiples plataformas más allá del ecosistema de Apple

Swift combina el rendimiento y la eficiencia de los lenguajes compilados con la simplicidad e interactividad de los lenguajes de scripting populares, lo que lo convierte en una excelente opción para iOS, macOS, watchOS, tvOS y desarrollo del lado servidor.

" copia de la funciónToClipboard() {} comandos const = document.querySelectorAll('code'); que todos losCommands = '; comandos. paraCada(cmd = confianza allCommands += cmd.textContent + '\n'); navigator.clipboard.writeText(allCommands); alerta ('Todos los comandos copiados a portapapeles!'); }

función generaPDF() { ventana.print(); } ■/script título