ÇSTech
Published in

ÇSTech

SwiftUI: @Published, @State, @StateObject, @ObservedObject

SwiftUI bize uygulamalarımız için farklı işlevsellik sağlayan birçok property wrapper sunar. Bu makalede @Published, @State, @StateObject ve @ObservedObject property wrapperlarının özelliklerini, kullanım amaçlarını ve farklarını örnekler üzerinde inceleyeceğiz.

@State

View üzerinde güncellenen veriler varsa bunları izleyip view’u yeniden çizmek için state kullanılır. State, view içinde depolayacağımız basit veri tipleri için (int, string, bool gibi) tasarlanmış bir property wrapper’dır. Class ve struct gibi karmaşık yapılar için uygun değildir. Öncelikle uygun olmayan tiplerde kullandığımızda nasıl bir sonuç alabiliriz bunu inceleyelim.

Yukarıda gördüğümüz kod bloğunda class tipinde bir değişkeni @State olarak işaretledik, bu state için uygun olmadığını söylediğim bir durum olsa dahi kod üzerinde herhangi bir hata almıyoruz. Peki sonuç ne olacak, nasıl çalışacak?

Loglarda değişkenin güncellendiğini görüyoruz fakat view üzerinde bir değişiklik göremiyoruz, @State olarak işaretlediğimiz nesne izlense de state yapısı gereği nesneye bağlı özelliği izleyememekte sadece nesnenin kendisi ile ilgilenmektedir. Bu nedenle view yeniden çizilmemiştir.

Kodumuzu yukarıdaki şekilde güncellediğimizde ise “Sayıyı Arttır” butonuna bastığımızda text’in güncellendiğini görüntüleyebileceğiz.

State basit tipler için tasarlanmıştır ve onlar ile uyumlu çalışır demiştik, peki ya daha karmaşık tipler için hangi property wrapperları kullanabiliriz?

@ObservedObject

Hemen bir örnek ile başlayalım.

ToplamViewModel nesnesi, ObservableObject protokolünü uyguladığı için @ObservedObject olarak tanımlayabildik. ObservableObject protokolü, nesnedeki değişiklikleri view üzerinden izlememizi, değişikliklerin algılanmasını ve view’in yeniden çizilmesini sağlar. ToplamView içerisinde viewModel için kullandığımız @ObservedObject property wrapper’i ile bu nesneyi view’da izleyebileceğiz.

Yukarıdaki örnekte +1 butonuna bastığımızda viewModel nesnesinin toplam özelliğini 1 sayı arttırarak ekranda göstermek istiyoruz. Fakat bir problem var, viewModel.toplam arttığı halde view üzerinde değişikliği görememekteyiz.

İşte tam burada karşımıza çıkan bir property wrappper daha var;

@Published

Published, değişiklikler meydana geldiğinde otomatik olarak bildiren gözlemlenebilir nesneler oluşturmamıza olanak tanır.

@Published olarak işaretlenmiş değişkene sahip bir nesne değiştirildiğinde, bu nesneyi kullanan tüm viewlar bu değişiklikleri yansıtmak için yeniden yüklenecektir.

Ufak bir düzeltme ile yukarıdaki örneğimizi butona basıldığında view üzerinde değişikliği görecek şekilde düzenleyebiliriz.

Toplam değişkenini @Published olarak işaretlediğimize göre artık sorunumuz ortadan kalktı. Published otomatik olarak değişimleri bildirecek ve view her güncellemede yeniden çizilecektir.

Peki bunu published kullanmadan manuel olarak yapamaz mıyız? Elbette yapabiliriz, objectWillChange.send() metodu ile view’i güncellemek istediğimiz yerde manuel olarak da güncelleyebilir, güncelleme işlemlerimizi ayrı koşullara alabilir ve @Published’in otomatik güncellemesinden yararlanmayabiliriz.

Bu şekilde toplam değişkenini her arttırdığımızda view’i güncellemek yerine sadece 10'dan büyük olduğu durumda güncelle diyebiliriz.

View içerisine başka bir view koyduğumuz bir örnek ile ObservedObject’i incelemeye devam edelim. Aşağıdaki kod bloğunda ObserverView içerisine yukarıda oluşturduğumuz ToplamView’i VStack içerisinde koyduk.

Buradaki kod bloğu bize ID yazan bir text, ID oluşturan bir buton ve altında daha önce gördüğümüz ToplamView elementlerini gösterecektir. ID Oluştur butonuna bastığımızda, oluşturan rastgele ID textlerini, ToplamView içerisindeki +1 butonuna bastığımızda ise toplamın arttığını göreceğiz.

Burada dikkatimizi çekmesi gereken bir durum var. Görüldüğü üzere ID Oluştur butonuna her basıldığında ToplamView içerisindeki viewModel var olan durumunu korumak yerine yeniden oluşturulmakta ve toplam sıfırlanmaktadır. İşte bu noktada karşımıza @StateObject çıkmakta.

@StateObject

StateObject, ObservedObject’ten farklı olarak nesneyi yeniden oluşturmak yerine var olan durumunu korur. Kullanımı bu şekilde ayrılmış olur. Uygulamadaki kurgumuza göre hangisini kullanacağımız bu özelliği ile önem arz eder.

Örnekte viewModel’i tanımladığımızda uyguladığımız @ObservedObject yerine @StateObject yazdığımızda nesnenin var olan durumunu koruduğunu görebiliriz.

Burada sona gelmiş bulunmaktayız. Daha fazla bilgi için aşağıdaki kaynakları inceleyebilirsiniz.

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store