Observer — nyckelbegrepp inom prenumerationsmönstret för ändringar

Författare: IT Sectr Publicerad: 2026-02-17 Lästid: 7 min

Observer — ett beteendemönster där ett objekt (utgivare) meddelar flera prenumeranter om förändringar i sitt tillstånd. Inom mobilutveckling ligger Observer till grund för reaktiva mekanismer: UI prenumererar på dataförändringar och uppdateras automatiskt. Mönstret är implementerat i NotificationCenter på iOS och LiveData/Flow på Android. Mer — på Refactoring Guru: Observer.

Huvudpunkter

  • Observer — prenumerationsmönster: en utgivare, flera prenumeranter
  • NotificationCenter — inbyggd implementation av Observer i iOS/macOS
  • Flow och LiveData — reaktiva implementationer av Observer i Android
  • Push vs Pull — utgivaren kan skicka data eller meddela om händelser
  • Minnesläckor — prenumeranter måste avsluta prenumerationen för att förhindra läckor

Vad är Observer: essensen av observatörsmönstret?

Observer (observatör) — ett GoF-beteendemönster som definierar ett «en-till-många»-beroende mellan objekt. När ett objekt (Subject eller Observable) ändrar tillstånd, meddelas och uppdateras alla beroende objekt (Observers) automatiskt. Mönstret implementerar lös koppling: utgivaren känner inte till prenumeranternas konkreta klasser — bara att de implementerar Observer-gränssnittet.

Observer-struktur inkluderar Subject-gränssnittet med metoderna attach(), detach(), notify() och Observer-gränssnittet med metoden update(). ConcreteSubject lagrar tillståndet och listan över prenumeranter. ConcreteObserver implementerar update() och reagerar på förändringar. Inom mobilutveckling förekommer den klassiska GoF-implementationen sällan — den ersätts av inbyggda mekanismer: NotificationCenter, Combine, Flow, LiveData, som implementerar samma idé med modernt API.

Push vs Pull-modell — i Push-modellen skickar Subject data till alla prenumeranter (NotificationCenter.post). I Pull-modellen meddelar Subject endast, och prenumeranten hämtar själv data. Android LiveData använder Push (data överförs i observe()), RxJava/Flow stöder båda modellerna. Valet beror på uppgiften: Push är enklare för UI-uppdateringar, Pull är effektivare för stora datamängder som prenumeranten kanske inte vill ta emot.

Observer i iOS: NotificationCenter, Combine och KVO

NotificationCenter — den inbyggda iOS/macOS-mekanismen för att implementera Observer. Utgivaren skickar Notification via NotificationCenter.default.post(name:, object:, userInfo:). Prenumeranten registrerar sig via addObserver(forName:, queue:, using:). NotificationCenter stöder namngivna meddelanden (Notification.Name) och kan överföra alla data i userInfo. UIKeyboardWillShowNotification, UIApplicationDidEnterBackgroundNotification — systemexempel.

swift
extension Notification.Name {
    static let userDidLogin = Notification.Name("userDidLogin")
}

// Utgivare
NotificationCenter.default.post(
    name: .userDidLogin,
    object: nil,
    userInfo: ["userId": "123"]
)

// Prenumerant
class ProfileViewModel {
    private var observers: [NSObjectProtocol] = []

    func startObserving() {
        let observer = NotificationCenter.default.addObserver(
            forName: .userDidLogin,
            object: nil,
            queue: .main
        ) { [weak self] notification in
            guard let userId = notification.userInfo?["userId"] as? String else { return }
            // Prenumeranten reagerar på händelsen
            self?.loadProfile(userId: userId)
        }
        observers.append(observer)
    }

    func stopObserving() {
        observers.forEach { NotificationCenter.default.removeObserver($0) }
        observers.removeAll()
    }
}

Combine framework — ett modernt reaktivt alternativ till NotificationCenter, tillgängligt från iOS 13. Publisher (NotificationCenter, URLSession.Timer) — utgivare, Subscriber (sink, assign) — prenumerant. Combine lägger till operatorer (map, filter, combineLatest) för transformation av dataströmmen. @Published — property wrapper som automatiskt meddelar prenumeranter om förändringar. I MVVM med SwiftUI ersätter Combine NotificationCenter för att koppla samman ViewModel och View.

KVO (Key-Value Observing) — en gammal ObjC/Swift-mekanism för att observera enskilda egenskaper hos objekt. @objc dynamic var name: String — observerad egenskap. observe(.name) — prenumeration. KVO fungerar endast med @objc-kompatibla klasser och ObjC-arv. Apple rekommenderar Combine och @Published istället för KVO i nya projekt. KVO förblir relevant för UIKit-kompatibilitet i hybridprojekt.

Observer i Android: LiveData, StateFlow och SharedFlow

LiveData — en komponent i Android Architecture Components för att implementera Observer. En Observable-klass som meddelar prenumeranter om dataförändringar. LiveData tar hänsyn till livscykeln: prenumeranter (LifecycleOwner) avslutar automatiskt prenumerationen vid förstörelse. LiveData är Push-modell: data överförs i observe(). LiveData är den grundläggande byggstenen för MVVM i Android före introduktionen av Jetpack Compose.

kotlin
// ViewModel — utgivare
class UserViewModel : ViewModel() {
    private val _user = MutableLiveData<User?>(null)
    val user: LiveData<User?> = _user

    fun loadUser(id: String) {
        viewModelScope.launch {
            val result = userRepository.getUser(id)
            _user.value = result
        }
    }
}

// Fragment — prenumerant
class UserFragment : Fragment() {
    private val viewModel: UserViewModel by viewModels()

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        viewModel.user.observe(viewLifecycleOwner) { user ->
            // Prenumeranten reagerar på ändringar
            userName.text = user?.name
            userEmail.text = user?.email
        }
    }
}

StateFlow och SharedFlow — reaktiva typer från Kotlin Coroutines som ersatte LiveData i Jetpack Compose. StateFlow — observerbar state holder med ett fast aktuellt värde. SharedFlow — konfigurerbar hot flow utan tillstånd, lämplig för engångshändelser (navigering, toast). Båda typerna är nära integrerade med Compose: collectAsState(), collectAsEffect(). StateFlow är obligatoriskt i moderna Android-projekt med Compose.

LiveData vs StateFlow — LiveData är bundet till Android Lifecycle, StateFlow är plattformsoberoende. StateFlow stöder coroutines, operatorer (map, filter) och testas utan Android-beroenden. LiveData är enklare för Java-kompatibilitet. Google rekommenderar StateFlow för nya projekt med Kotlin + Compose, LiveData — för stöd av gamla projekt eller Java-kod.

Hantera prenumerationer och minnesläckor

Minnesläckor (memory leaks) — huvudproblemet med Observer utan korrekt prenumerationshantering. Om en prenumerant (Activity, Fragment, UIViewController) förstörs men inte avslutar prenumerationen, fortsätter utgivaren att hålla en referens till den, och garbage collector kan inte frigöra minnet. I Android måste LifecycleOwner (Activity/Fragment) anropa removeObserver() eller använda observe(viewLifecycleOwner). I iOS — removeObserver i deinit eller disposeBag i Combine.

PlattformObserver-mekanismAutomatisk avprenumerationManuell avprenumeration
iOSNotificationCenterNejremoveObserver() i deinit
iOSCombine (sink)Nejstore(in: &bag) — DisposeBag
iOSKVONejremoveObserver() i deinit
AndroidLiveDataJa (LifecycleOwner)removeObserver() valfritt
AndroidStateFlowVia viewModelScopecancel() Job vid avprenumeration
AndroidRxJavaNejdispose() i CompositeDisposable

Svag referens (weak reference) i prenumeranter — i prenumerationsblocket använd [weak self] i Swift och hänvisa till lifecycle scope i Kotlin. LiveData hanterar automatiskt prenumerationen via LifecycleOwner — prenumerationen är endast aktiv när Lifecycle är i tillståndet STARTED eller RESUMED. StateFlow i Compose använder collectAsState() med hänsyn till lifecycle. NotificationCenter i iOS kräver explicit [weak self], eftersom closure starkt refererar till self.

Observer vs Publisher-Subscriber: vad är skillnaden

Observer (GoF) och Publisher-Subscriber (PubSub) — liknande men olika mönster. I Observer meddelar utgivaren direkt prenumeranter genom att anropa deras metoder. Utgivaren känner till prenumeranterna (lagrar en lista). I PubSub känner utgivaren och prenumeranten inte till varandra — det finns en förmedlare (Event Bus, Message Queue, NotificationCenter) mellan dem. Utgivaren skickar ett meddelande till en kanal, prenumeranten lyssnar på kanalen. PubSub ger lösare koppling.

Exempel på PubSub inom mobilutveckling — NotificationCenter i iOS kan betraktas som PubSub: utgivaren känner inte prenumeranterna — den publicerar bara ett meddelande. EventBus eller Otto i Android (föråldrade). SharedFlow med BroadcastChannel — PubSub i Kotlin-världen. I distribuerade system implementeras PubSub via RabbitMQ, Kafka, Google PubSub. För mobilutveckling är PubSub användbart i modulär arkitektur, där moduler inte ska vara beroende av varandra.

Vad du ska välja — för UI-uppdateringar (ViewModel → View) använd Observer (LiveData, StateFlow, @Published). För intermodulära händelser (autentisering, utloggning, temabytning) — PubSub (SharedFlow, NotificationCenter, EventBus). Observer är enklare och effektivare inom en skärm, PubSub är flexiblare för globala händelser men svårare att felsöka på grund av implicita beroenden.

Vanliga frågor

Vad skiljer StateFlow från LiveData?

StateFlow är en plattformsoberoende typ från Kotlin Coroutines, LiveData är bundet till Android Lifecycle. StateFlow stöder coroutines och operatorer, testas utan Android. LiveData hanterar prenumerationen automatiskt via LifecycleOwner. Google rekommenderar StateFlow för nya projekt med Kotlin + Compose, LiveData — för Java-kompatibilitet.

Hur undviker jag minnesläckor med NotificationCenter?

Använd [weak self] i handler-closure och anropa removeObserver() i deinit. Behåll en referens till observer (NSObjectProtocol) och ta bort den vid objektets förstörelse. I Combine, använd AnyCancellable och store(in:) för automatisk avprenumeration vid frigöring av DisposeBag.

Kan jag använda Observer i SwiftUI utan Combine?

Ja, SwiftUI stöder ObservableObject med @Published och @StateObject/@ObservedObject — detta är en inbyggd implementation av Observer. @Published meddelar automatiskt View om förändringar. Combine är inte obligatoriskt: ObservableObject använder den i SwiftUI inbyggda objectWillChange Publishing. Combine lägger till operatorer för strömtransformering.

När ska jag använda SharedFlow istället för StateFlow?

SharedFlow — för engångshändelser (navigering, toast, Snackbar) där inget aktuellt värde behövs. StateFlow — för UI-tillstånd (datalista, laddningsförlopp) där en aktuell ögonblicksbild behövs. SharedFlow har ingen value-egenskap och returnerar inte det senaste värdet till nya prenumeranter.

Vad är skillnaden mellan KVO och Combine i iOS?

KVO är en föråldrad ObjC-mekanism, kräver @objc dynamic och fungerar endast med klasser som ärver från NSObject. Combine är ett modernt Swift-ramverk, typsäkert, med operatorer och integration med SwiftUI. Combine ersätter KVO och NotificationCenter. Apple rekommenderar Combine för nya projekt, KVO — endast för stöd av gammal kod.

Sammanfattning

  • Observer — beteendemönster för att meddela prenumeranter om förändringar
  • iOS NotificationCenter — PubSub-implementation med namngivna meddelanden
  • iOS Combine — reaktivt ramverk med Publisher och Subscriber
  • Android LiveData — lifecycle-aware Observer från Android Architecture Components
  • Android StateFlow — reaktiv state holder för Compose och coroutines
  • Minneshantering — obligatorisk avprenumeration för att förhindra läckor
  • Observer vs PubSub — direkt prenumeration vs förmedlare för lös koppling

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.

Diskutera projektet

Läs också