Swift är Apples programmeringsspråk som kombinerar styrkan från Objective-C med säkerheten från moderna språk. Till skillnad från många andra språk erbjuder Swift unika konstruktioner: värdetyper med automatisk kopiering, Actors med isolering på kompilatornivå, Property Wrappers för återanvändning av egenskapslogik och Protokollorienterad Programmering som ett alternativ till klassiskt arv. Enligt Apple Swift-dokumentationen gör dessa funktioner koden säkrare och mer prestandaeffektiv.
Huvudpunkter
I Swift är struct en värdetyp medan class är en referenstyp. Denna grundläggande skillnad bestämmer beteendet vid tilldelning, överföring till funktioner och minneshantering. Struct kopieras i sin helhet vid varje tilldelning, class skickas via referens — endast pekaren till heap-objektet kopieras.
Struct implementerar automatiskt värdesemantik — varje instans är oberoende. Mutation av en struct-egenskap är endast möjlig via var och metoder som ändrar egenskaper måste markeras som mutating. Struct stöder inte arv men kan följa protokoll. Swifts standardbibliotek använder struct för String, Array, Dictionary, Int, Bool — alla grundläggande typer är värdetyper.
struct User {
let id: Int
var name: String
mutating func updateName(_ newName: String) {
name = newName
}
}
var user1 = User(id: 1, name: "Alice")
var user2 = user1
user2.updateName("Bob")
// user1.name === "Alice", user2.name === "Bob"
// Fullständig kopia — oberoende instanser
Class lagras i heapen och stöder referensiakthet. Flera variabler kan referera till samma objekt, ändringar via en referens är synliga genom alla andra. Class stöder arv, tillåter metodöverskrivning (override), har deinit för resursrensning. I Swift används class mer sällan än struct — Apple rekommenderar att börja med struct och endast byta till class när arv eller referenssemantik behövs.
class Car {
let model: String
var speed: Int
init(model: String, speed: Int) {
self.model = model
self.speed = speed
}
func accelerate(_ amount: Int) {
speed += amount
}
}
let car1 = Car(model: "Tesla", speed: 0)
let car2 = car1
car2.accelerate(50)
// car1.speed === 50, car2.speed === 50
// Samma referens — ändringar synliga överallt
Valet mellan struct och class beror på datasemantik. För konfigurationer, datamodeller och tillstånd använd struct — kopiering är säkrare och mer förutsägbar. För objekt med identitet (användarsession, databasanslutning) och när arv behövs, använd class.
Actor är en referenstyp som skyddar sitt föränderliga tillstånd från samtidig åtkomst. Swift-kompilatorn garanterar att actor-variabler endast kan nås från samma actor-kontext — all extern åtkomst orsakar ett kompileringsfel. Detta förhindrar datakapplöpningar på språknivå, utan manuella låsningar.
Alla actor-egenskaper och -metoder är isolerade som standard. Att anropa en actor-metod utifrån kräver await — Swift växlar exekvering till actor och tillbaka. Actor synkroniserar åtkomst sekventiellt: förfrågningar från olika uppgifter köas. Detta garanterar konsekvent tillstånd inuti actor. Icke-isolerade metoder (nonisolated) kan anropas utan await men kan inte komma åt föränderliga egenskaper.
actor BankAccount {
private var balance: Double
init(initialBalance: Double) {
balance = initialBalance
}
func deposit(amount: Double) {
balance += amount
}
func withdraw(amount: Double) throws {
guard balance >= amount else {
throw BankError.insufficientFunds
}
balance -= amount
}
nonisolated func accountInfo() -> String {
return "Bankkonto"
}
}
let account = BankAccount(initialBalance: 1000)
await account.deposit(amount: 500)
// balance = 1500 — atomärt, utan kapplöpningstillstånd
Actor är användbar för tillståndshanterare, cacheminnen och nätverkstjänster där flera uppgifter samtidigt läser och skriver data. Till skillnad från manuell synkronisering via NSLock eller DispatchQueue kontrolleras actor vid kompilering — det är omöjligt att göra fel. Isoleringsfel uppträder vid kompilering, inte vid körning.
Property Wrapper är en annotering som lägger till beteende till en egenskap utan att ändra dess deklaration. SwiftUI och Combine tillhandahåller inbyggda wrappers för hantering av vyernas tillstånd. Kompilatorn genererar kod som omsluter egenskapsåtkomsten, och lägger till logik för observation, synkronisering eller transformation.
@Published används i klasser som följer ObservableObject för att automatiskt publicera ändringar. Combine-prenumeranter får meddelanden vid varje uppdatering. @State är det lokala tillståndet för en SwiftUI-vy. SwiftUI ritar automatiskt om vyn när @State ändras. @Binding skapar en tvåvägsförbindelse mellan en förälder- och barnvy utan att äga datan.
import SwiftUI
import Combine
@main
struct CounterApp: App {
var body: some Scene {
WindowGroup {
ContentView()
}
}
}
class CounterViewModel: ObservableObject {
@Published var count: Int = 0
func increment() {
count += 1
}
}
struct ContentView: View {
@State private var greeting: String = "Hej"
@StateObject private var viewModel = CounterViewModel()
var body: some View {
VStack {
CounterDisplay(count: $viewModel.count)
Text(greeting)
Button("Öka", action: viewModel.increment)
}
}
}
struct CounterDisplay: View {
@Binding var count: Int
var body: some View {
Text("Räkning: \(count)")
}
}
Anpassade Property Wrappers skapas med @propertyWrapper och en struktur med ett wrappedValue-fält. Detta möjliggör återanvändning av logik: validering, normalisering, UserDefaults-lagring. Property Wrappers minskar avsevärt boilerplate-kod och gör utvecklarens avsikt explicit genom annotering.
@propertyWrapper
struct Clamped<T: Comparable> {
private var value: T
let range: ClosedRange<T>
init(wrappedValue: T, range: ClosedRange<T>) {
self.range = range
self.value = min(max(wrappedValue, range.lowerBound), range.upperBound)
}
var wrappedValue: T {
get { value }
set { value = min(max(newValue, range.lowerBound), range.upperBound) }
}
}
struct Settings {
@Clamped(range: 0...100) var volume: Int = 50
}
var s = Settings()
s.volume = 150
// s.volume === 100 — värdet automatiskt begränsat
Generics är en kraftfull mekanism i Swift för att skriva flexibel kod utan förlust av typsäkerhet. Generiska funktioner och typer fungerar med alla typer som uppfyller begränsningarna. Protokollorienterad Programmering (POP) är ett Swift-paradigm där protocol + extension ersätter klassiskt klassarv och ger beteendekomposition.
Swift tillåter att begränsa generiska parametrar med protokoll (where-satser). Protokoll med associerad typ är den generiska motsvarigheten för protokoll: den konkreta typen bestäms vid tidpunkten för efterlevnad. Detta är grunden för typsäkra samlingar och algoritmer. Swifts standardbibliotek använder aktivt Generics: Array, Dictionary, Optional — alla är generiska typer.
protocol Cacheable {
associatedtype Key: Hashable
associatedtype Value
func get(_ key: Key) -> Value?
mutating func set(_ value: Value, for key: Key)
}
struct MemoryCache<K: Hashable, V>: Cacheable {
private var storage: [K: V] = [:]
typealias Key = K
typealias Value = V
func get(_ key: K) -> V? {
return storage[key]
}
mutating func set(_ value: V, for key: K) {
storage[key] = value
}
}
func firstMatch<T: Equatable>(in array: [T], target: T) -> Int? {
for (index, item) in array.enumerated() {
if item == target {
return index
}
}
return nil
}
let numbers = [10, 20, 30, 40]
let index = firstMatch(in: numbers, target: 30)
// index === 2 — en generisk metod för alla Equatable-typer
Protokolltillägg är en nyckelmekanism i POP. I ett tillägg kan standardimplementeringar av protokollmetoder tillhandahållas. Typer som följer protokollet får denna implementering gratis och kan åsidosätta den vid behov. Detta gör det möjligt att bygga beteendehierarkier utan klassarv — ett alternativ till multipelt arv, som inte finns i Swift.
protocol Drivable {
var speed: Double { get set }
func drive()
}
extension Drivable {
func drive() {
if speed > 0 {
print("Kör i \(speed) km/h")
}
}
}
struct Bicycle: Drivable {
var speed: Double = 15
}
struct Plane: Drivable {
var speed: Double = 900
func drive() {
print("Flyger i \(speed) km/h")
}
}
let bike = Bicycle()
bike.drive() // "Kör i 15.0 km/h" — standard
let plane = Plane()
plane.drive() // "Flyger i 900.0 km/h" — åsidosatt
POP med tillägg möjliggör komposition via flera protokoll — en typ kan följa flera protokoll och få deras implementeringar. Detta är mer flexibelt än enskilt klassarv där hela hierarkin är fast. Swifts standardbibliotek är byggt på POP: CustomStringConvertible, Equatable, Hashable, Codable — alla är protokoll med tillägg.
Enum i Swift är en betydligt kraftfullare konstruktion än i andra språk. Varje fall kan ha associerade värden — en godtycklig uppsättning data av vilken typ som helst. I kombination med tillägg och mönstermatchning blir enum grunden för att modellera tillstånd, operationsresultat och finita tillståndsmaskiner.
Associerade värden gör att varje fall kan lagra unika data. Till exempel innehåller fallet loading inga data, success innehåller resultatet, failure innehåller ett fel. Mönstermatchning via switch extraherar de associerade värdena och bearbetar varje fall. Kompilatorn kontrollerar fullständighet (exhaustive switch) — detta eliminerar bortglömda tillstånd.
enum NetworkResult<T> {
case loading
case success(T)
case failure(Error)
}
enum MediaFile {
case image(url: URL, width: Int, height: Int)
case video(url: URL, duration: Double)
case audio(url: URL, bitrate: Int)
}
func handle(_ result: NetworkResult<String>) {
switch result {
case .loading:
print("Laddar...")
case .success(let data):
print("Mottaget: \(data)")
case .failure(let error):
print("Fel: \(error.localizedDescription)")
}
}
let file = MediaFile.video(url: URL(string: "https://example.com/video.mp4")!, duration: 120)
if case .video(let url, let duration) = file {
print("Video \(url) längd \(duration)s")
}
Swift tillåter att lägga till metoder, beräknade egenskaper och protokollefterlevnad via tillägg för enum. Detta kräver inte att den ursprungliga deklarationen ändras — koden förblir ren och modulär. Metoder i tillägg kan arbeta med associerade värden, beräkna härledd data och implementera affärslogik.
extension MediaFile {
var fileName: String {
switch self {
case .image(let url, _, _),
.video(let url, _),
.audio(let url, _):
return url.lastPathComponent
}
}
var description: String {
switch self {
case .image(_, let w, let h):
return "Bild \(w)x\(h)"
case .video(_, let d):
return "Video \(d)s"
case .audio(_, let b):
return "Ljud \(b) kbps"
}
}
}
extension MediaFile: Equatable {
static func == (lhs: MediaFile, rhs: MediaFile) -> Bool {
return lhs.fileName == rhs.fileName
}
}
let files: [MediaFile] = [file]
files.forEach { print($0.description) }
// "Video 120.0s"
Enum med associerade värden + tillägg är ersättningen för förseglade klasser från Kotlin eller diskriminerade unioner från andra språk. Swift använder denna kombination för Result (en standardtyp i standardbiblioteket), Optional (Optional är en enum med .none och .some) och tillståndshantering i SwiftUI. Mönstermatchning garanterar att alla tillstånd hanteras — körningsfel är omöjliga.
Vanliga Frågor
Struct — värdetyp, kopieras vid tilldelning, stöder inte arv. Class — referenstyp, skickas via referens, stöder arv, deinit och identitetskontroll (===). Apple rekommenderar att börja med struct och endast byta till class när referenssemantik behövs.
Actor — trådsäker referenstyp. Kompilatorn förbjuder samtidig åtkomst till föränderligt tillstånd från olika kontexter. Använd Actor för tillståndshanterare, cacheminnen och tjänster som nås av flera uppgifter. Anrop av actor-metoder kräver await.
Huvudsakliga: @State — lokalt vyläge; @Binding — datakoppling utan ägande; @Published — publicering av ändringar i ObservableObject; @StateObject — ägande av ObservableObject; @EnvironmentObject — beroende från miljön. Anpassade wrappers skapas via @propertyWrapper.
POP — ett paradigm där protocol + extension definierar beteende istället för klassarv. En typ följer flera protokoll och får deras implementeringar gratis. Detta är komposition istället för arv — mer flexibelt och säkrare. Swifts standardbibliotek (Equatable, Codable) är byggt på POP.
Enum i Swift stöder associerade värden — varje fall kan lagra godtycklig data av olika typer. I kombination med mönstermatchning (switch) ger detta en kraftfull modell för tillstånd, fel och domändriven design. Optional och Result är standard Swift-enumar med associerade värden.
Sammanfattning
Vi utvecklar en mobil applikation nyckelfärdigt
IT Sectr skapar iOS- och Android-applikationer för startups och företag sedan 2017. Vi ger dig råd och föreslår den bästa lösningen.