Published on

SwiftUI-da @Observable macro

Authors

iOS 17 da Apple Swift tiliga macro qo'llab-quvvatlashni qo'shdi. Shu bilan birga, view model va boshqa kuzatiluvchi obyektlar uchun yangi, soddaroq usul β€” @Observable macro paydo bo'ldi. Bu eski ObservableObject protokoliga muqobil.

@Observable faqat iOS 17 va undan yuqori versiyalarni qo'llab-quvvatlovchi loyihalarda ishlatiladi. Agar ilovangiz eski iOS versiyalarini ham qo'llab-quvvatlasa, ObservableObject ishlatishda davom etish kerak β€” bu eskirgan (deprecated) emas va uzoq vaqt ishlayveradi.


Eski usul β€” ObservableObject

class ObservableViewModel: ObservableObject {
    @Published var title: String = "Boshlang'ich sarlavha"
}

Ota viewda:

struct ParentView: View {

    @StateObject private var viewModel = ObservableViewModel()

    var body: some View {
        Button(viewModel.title) {
            viewModel.title = "Yangi sarlavha"
        }
    }
}

Bola viewga uzatishda:

struct ChildView: View {

    @ObservedObject var viewModel: ObservableViewModel

    var body: some View {
        Button(viewModel.title) {
            viewModel.title = "Bola viewdan o'zgartirildi"
        }
    }
}

Environment orqali uzatishda:

struct ThirdView: View {

    @EnvironmentObject var viewModel: ObservableViewModel

    var body: some View {
        Button(viewModel.title) {
            viewModel.title = "Uchinchi viewdan o'zgartirildi"
        }
    }
}

// Ota viewda environment-ga qo'shish:
ThirdView()
    .environmentObject(viewModel)

Yangi usul β€” @Observable

@Observable macro ObservableObject protokoliga muqobil. Bu macro klassga avtomatik ravishda kerakli kodni qo'shadi.

@Observable
class ObservableViewModel {
    var title: String = "Boshlang'ich sarlavha"
}

O'zgarishlar ro'yxati

Eski usulYangi usul
class X: ObservableObject@Observable class X
@Published var titlevar title (hech qanday belgisiz)
@StateObject private var viewModel@State private var viewModel
@ObservedObject var viewModel@Bindable var viewModel
@EnvironmentObject var viewModel@Environment(ViewModel.self) var viewModel
.environmentObject(viewModel).environment(viewModel)

Eng muhim farq β€” @Published kerak emas

ObservableObject-da view-ni yangilash kerak bo'lgan har bir xususiyatga @Published qo'shish kerak edi. @Observable-da esa barcha xususiyatlar standart holatda kuzatiladi β€” alohida belgi qo'yish shart emas.

Agar biror xususiyat view-ni yangilamasligi kerak bo'lsa, uni @ObservationIgnored bilan belgilash kerak:

@Observable
class ObservableViewModel {
    var title: String = "Kuzatiladi"           // standart β€” kuzatiladi

    @ObservationIgnored
    var internalCounter: Int = 0                // kuzatilmaydi
}

Bu eski usulga teskari mantiq: avval hamma narsa kuzatilmaydi edi, kerak bo'lganini @Published bilan qo'shish kerak edi. Endi hamma narsa kuzatiladi, kerak bo'lmaganini @ObservationIgnored bilan chiqarib tashlash kerak.


Yangi usulda to'liq misol

@Observable
class ObservableViewModel {
    var title: String = "Boshlang'ich sarlavha"
}

struct ParentView: View {

    @State private var viewModel = ObservableViewModel()

    var body: some View {
        VStack(spacing: 40) {
            Button(viewModel.title) {
                viewModel.title = "Yangi sarlavha"
            }

            ChildView(viewModel: viewModel)
            ThirdView()
        }
        .environment(viewModel)
    }
}

struct ChildView: View {

    @Bindable var viewModel: ObservableViewModel

    var body: some View {
        Button(viewModel.title) {
            viewModel.title = "Bola viewdan o'zgartirildi"
        }
    }
}

struct ThirdView: View {

    @Environment(ObservableViewModel.self) var viewModel

    var body: some View {
        Button(viewModel.title) {
            viewModel.title = "Uchinchi viewdan o'zgartirildi"
        }
    }
}

Uchala view ham bitta viewModel obyektini kuzatadi va istalgan biridan o'zgartirish boshqalarga ham aks etadi.


Migratsiya tartibi

Apple-ning rasmiy hujjatlarida ko'rsatilgan qadamlar:

  1. : ObservableObject ni olib tashlang, o'rniga @Observable qo'shing
  2. Barcha @Published var dan @Published ni olib tashlang
  3. @StateObject o'rniga @State ishlating
  4. @ObservedObject o'rniga @Bindable ishlating
  5. @EnvironmentObject o'rniga @Environment(Type.self) ishlating
  6. .environmentObject(obj) o'rniga .environment(obj) ishlating

Migratsiyani bosqichma-bosqich amalga oshirish tavsiya etiladi. Mavjud loyihani to'liq qayta yozish shart emas β€” yangi fayllar yozilganda yangi usulni qo'llash, eski kodni esa kerak bo'lganda o'zgartirish yetarli.


Thread xavfsizligi haqida eslatma

@Observable-ga o'tish view yangilanishlarini boshqarish usulini o'zgartiradi, lekin bu thread mantiqini o'zgartirmaydi. UI yangilanishlari hamon main thread-da bajarilishi shart β€” @Observable bu masalani hal qilmaydi.


Xulosa

Bu videoda o'rgandik:

  • @Observable β€” ObservableObject protokoliga muqobil, iOS 17+ uchun yangi macro
  • @Published kerak emas β€” barcha xususiyatlar standart holatda kuzatiladi
  • Kuzatilmasligi kerak bo'lgan xususiyatlar uchun @ObservationIgnored
  • @StateObject β†’ @State, @ObservedObject β†’ @Bindable, @EnvironmentObject β†’ @Environment(Type.self)
  • Eski va yangi usul parallel ishlatilishi mumkin β€” ObservableObject eskirmagan
  • Migratsiya bosqichma-bosqich, yangi kod yozilganda amalga oshirilishi tavsiya etiladi

Keyingi videoda yangi mavzu bilan davom etamiz.

Buy mea coffee