Thuta Learning
ရှာဖွေရန်
AdvancedMobile Developmentintermediate

Dependency Injection (Environment)

စိတ်လျှော့ပါ။ ဒီခန်းကို စာအုပ်လိုမဟုတ်ဘဲ စကားပြောသလိုပဲ၊ နားလည်လွယ်အောင် ရှင်းပါမယ်။

ဒီခန်းပြီးရင် ဘာတတ်သွားမလဲ

  • Dependency Injection (Environment) ကို ကြောက်စရာမလိုအောင် နားလည်မယ်
  • ကိုယ်တိုင် Xcode/SwiftUI code ကို run ကြည့်တတ်မယ်
  • Real project ထဲမှာ ဒီ concept ကို ချက်ချင်း အသုံးချတတ်မယ်

ခဏလေး ဒီလိုပဲ စဉ်းစားကြည့်

Dependency Injection (DI) ဆိုတာ class/View ကို 'ကိုယ့်ဒီပန်ဒင့်စီတွေကို ကိုယ်တိုင် create မလုပ်ဘဲ, ပြင်ပက ပေးပို့ခံရတယ်' ဆိုတဲ့ pattern ပါ — testing/maintainability ပိုကောင်းစေပါတယ်။ SwiftUI က Hilt (Android tutorial) လို third-party DI library မလိုအပ်ဘဲ, built-in `Environment` mechanism (`.environmentObject()`, `@EnvironmentObject`) ကို ပေးထားပါတယ် — root View မှာ dependency ကို `.environmentObject(weatherApi)` လို့ inject ထားရင်, child View (nested level ဘယ်လောက်ပဲ ရှိရှိ) ကနေ `@EnvironmentObject var weatherApi: WeatherApi` လို့ ခေါ်ယူနိုင်ပါတယ်.

လက်တွေ့ scenario နဲ့ ချိတ်ကြည့်မယ်

`ContentView().environmentObject(WeatherApi())` လို့ root မှာ inject ထားရင် — nested View (`WeatherScreen` → `WeatherDetailCard` → `TemperatureLabel`) ဘယ်လောက်ပဲ deep ဖြစ်ဖြစ်, `@EnvironmentObject var weatherApi: WeatherApi` လို့ ခေါ်ယူနိုင်ပါတယ် — parameter တစ်ဆင့်ချင်း manual pass (`WeatherScreen(api:) → WeatherDetailCard(api:) → ...`) ရေးစရာ မလိုတော့ပါ.

အတူတူ ကြည့်မယ်

swift
// Root
@main
struct MyApp: App {
    @StateObject private var weatherApi = WeatherApiClient()

    var body: some Scene {
        WindowGroup {
            ContentView()
                .environmentObject(weatherApi)
        }
    }
}

// Deeply nested child — no manual parameter passing needed
struct TemperatureLabel: View {
    @EnvironmentObject var weatherApi: WeatherApiClient

    var body: some View {
        Text("Connected: \(weatherApi.isReady)")
    }
}
You should see
TemperatureLabel (deeply nested) ကို parameter manual pass မလိုဘဲ weatherApi instance ကို access လုပ်နိုင်တာ တွေ့ရမည်။

၅ မိနစ် စမ်းကြည့်

`WeatherApiClient` (simple ObservableObject) ကို root မှာ `.environmentObject()` ဖြင့် inject ကြည့်ပြီး, nested View level ၂-၃ ဆင့် အောက်ကနေ `@EnvironmentObject` နဲ့ ခေါ်ယူကြည့်ပါ။

သတိလေးတစ်ချက်

`@EnvironmentObject` ရဲ့ dependency ကို root မှာ inject မထားရင် compile-time error မဟုတ်ဘဲ runtime crash ဖြစ်တတ်ပါတယ် (SwiftUI Preview ထဲမှာလည်း ထပ်တူ inject ပေးထားရပါမယ်) — production build မတိုင်ခင် Preview panel ကနေတောင် ဒီ error မျိုးကို ကြိုတွေ့နိုင်ပါတယ်။

ဒီနေရာမှာ လူအများမှားတတ်တယ်

  • `.environmentObject()` ကို root မှာ inject ဖို့ မေ့ဘဲ, child View ကနေ `@EnvironmentObject` ကို သုံးကြိုးစားခြင်း — runtime crash ('No ObservableObject of type... found') ဖြစ်ပါလိမ့်မယ်
  • App state အားလုံးကို Environment ထဲ shove လုပ်ခြင်း — dependency ဘယ်ဟာက ဘယ် View ကို affect လုပ်လဲ ခြေရာခံရခက်ခဲသွားနိုင်ပါတယ်

အခု ကိုယ်တိုင် စမ်းကြည့်

`WeatherApiClient` (simple ObservableObject) ကို root မှာ `.environmentObject()` ဖြင့် inject ကြည့်ပြီး, nested View level ၂-၃ ဆင့် အောက်ကနေ `@EnvironmentObject` နဲ့ ခေါ်ယူကြည့်ပါ။

You'll know it worked when: TemperatureLabel (deeply nested) ကို parameter manual pass မလိုဘဲ weatherApi instance ကို access လုပ်နိုင်တာ တွေ့ရမည်။

Dependency Injection (Environment) | Thuta Learning