Tilbake til bloggen
Guide28. februar 2026

Swift: Hva jeg lærte av å bygge Skoletime for iOS

Jeg er primært en webutvikler. TypeScript, React, Next.js — det er verktøyene jeg bruker til daglig. Men da ideen til Skoletime dukket opp — en tidsregistreringsapp for Osloskoler — visste jeg at det måtte bli en native iOS-app. Lærere trenger noe som fungerer offline, starter raskt, og føles naturlig på enheten. En webapp i Safari ville ikke kuttet det.

Så jeg åpnet Xcode for første gang, startet med Swift-dokumentasjonen, og begynte å bygge. Dette innlegget handler om den overgangen — hva som overrasket meg, hva som var lettere enn forventet, og hva jeg ville gjort annerledes.

Skoletime: Konteksten

Skoletime er et tidsregistreringssystem for skoler i Oslo. Lærere registrerer timer, vikarer, og fravær. Administrasjonen får oversikt over ressursbruk. Det høres enkelt ut, men detaljene er mange: forskjellige stillingstyper, overlappende timeplaner, godkjenningsflyter, og rapportering.

Appen måtte fungere pålitelig på iPad-er som lærerne bruker i klasserommet. Offline-støtte var kritisk — skolenes Wi-Fi er ikke alltid stabilt. Og brukergrensesnittet måtte være intuitivt nok til at en lærer kunne registrere en time på under 30 sekunder mellom undervisningsøkter.

SwiftUI vs UIKit

Det første valget var SwiftUI eller UIKit. UIKit har eksistert siden 2008 og har mye mer dokumentasjon og community-støtte. SwiftUI er Apples moderne deklarative rammeverk, lansert i 2019. Som en som kommer fra React var valget åpenbart — SwiftUI sin deklarative tilnærming føltes umiddelbart kjent.

struct TimeEntryView: View {
    @State private var selectedDate = Date()
    @State private var hours: Double = 1.0
    @State private var note = ""

    var body: some View {
        Form {
            DatePicker("Dato", selection: $selectedDate, displayedComponents: .date)

            Stepper("Timer: \(hours, specifier: "%.1f")", value: $hours, in: 0.5...12, step: 0.5)

            TextField("Notat (valgfritt)", text: $note)

            Button("Registrer") {
                saveEntry()
            }
            .disabled(hours <= 0)
        }
        .navigationTitle("Ny registrering")
    }
}

Hvis du kan React, ser du mønsteret med en gang. @State er som useState. Viewet er en funksjon av state. Binding med $-prefikset er toveis databinding — noe React bevisst unngår, men som fungerer utmerket i SwiftUI. Form og DatePicker gir deg iOS-native UI-komponenter automatisk, med riktig utseende og animasjoner.

Men SwiftUI har sine begrensninger. Komplekse lister med mange elementer kan bli trege. Navigasjon-APIet har endret seg mellom iOS-versjoner, noe som gjør migrering frustrerende. Og noen ganger må du falle tilbake til UIKit for funksjonalitet SwiftUI ikke støtter ennå.

Typesystemet: Swift vs TypeScript

Som TypeScript-utvikler elsker jeg typer. Swift tar det et steg videre — det er et genuint sterkt typet språk, ikke et typesystem lagt oppå et dynamisk språk. Ingen any å gjemme seg bak.

Codable-protokollen er et godt eksempel på dette. I TypeScript definerer du en type og håper at runtime-dataene matcher. I Swift garanterer kompilatoren at encoding og decoding fungerer:

struct TimeEntry: Codable, Identifiable {
    let id: UUID
    let teacherId: String
    let date: Date
    let hours: Double
    let note: String?
    let status: EntryStatus
    let createdAt: Date

    enum EntryStatus: String, Codable {
        case draft
        case submitted
        case approved
        case rejected
    }
}

Codable betyr at Swift automatisk kan serialisere og deserialisere denne strukturen til og fra JSON. Identifiable gjør at SwiftUI kan bruke den i lister uten ekstra konfigurasjon. String? med spørsmålstegnet betyr at feltet er optional — Swift tvinger deg til å håndtere null-tilfellet eksplisitt, noe som eliminerer en hel kategori av bugs.

Sammenlignet med TypeScript savner jeg union types og mapped types. Swift har enums med associated values som dekker noen av de samme bruksområdene, men det føles mer rigid. På den andre siden er Swift sin guard let og if let for optional-håndtering renere enn TypeScript sin optional chaining i mange situasjoner.

Xcode-opplevelsen

La meg være ærlig: Xcode er frustrerende. Etter å ha brukt VS Code og Cursor — lette, raske editorer med et rikt plugin-økosystem — føles Xcode tungt og ufleksibelt. Indeksering tar tid. Autocomplete er treg. Feilmeldingene er ofte kryptiske.

Men Xcode har styrker som ingen annen editor matcher. Interface Builder og SwiftUI Previews lar deg se UI-endringer i sanntid. Instruments gir deg dyp innsikt i minnebruk, CPU-profil og nettverksaktivitet. Simulator-integrasjonen er sømløs.

Min arbeidsflyt ble til slutt en hybrid: jeg skriver forretningslogikk og datamodeller i Cursor (med Swift-støtte via extensions), og bruker Xcode for UI-arbeid, debugging og testing på simulator.

Erfaringer fra overgangen

Start med SwiftUI. Hvis du kommer fra React, vil det deklarative paradigmet føles hjemme. UIKit er viktig å forstå for edge cases, men SwiftUI er riktig utgangspunkt i 2026.

Lær Combine eller async/await tidlig. Asynkron programmering i Swift har modnet enormt. async/await i Swift føles nesten identisk med JavaScript — men med kompilator-garantier for trådsikkerhet.

Forstå Apples økosystem. App Store-review, provisioning profiles, sertifikater — dette er en verden som ikke eksisterer i webutvikling. Planlegg ekstra tid til det.

Offline-first er lettere i native. Core Data og SwiftData gir deg en lokal database med synkroniseringsstøtte. For Skoletime var dette avgjørende — lærerne registrerer timer uten å tenke på nettverksstatus.

Oppsummering

Å bygge Skoletime med Swift var en investering. Læringskurven var bratt, Xcode var frustrerende, og Apple-økosystemet har sine egne regler. Men resultatet er en app som føles riktig på iOS — rask, pålitelig, og med et brukergrensesnitt som lærerne faktisk liker å bruke. For webutviklere som vurderer native iOS: det er verdt det, men forvent å bruke mer tid enn du tror.

#swift#ios#xcode#skoletime

Nyhetsbrev

Få nye innlegg rett i innboksen.