Sitemap

MVVM Base Protocols Hakkında Her Şey

5 min readJun 9, 2022

--

Press enter or click to view image in full size

Giriş

MVVM çok tercih edilen bir mimari. Ben de projelerimde MVVM mimarisini sıklıkla tercih ediyorum. Son zamanlarda farkettim ki yeni bir projeye başlarken sürekli önceki projelerimden kopya çekiyorum hatta birçok yerini kopyala-yapıştır yapıyorum. Bundan sıkılıp daha iyi bir yol aradım ve karşıma SDK üretmek çıktı. Üstelik bunu beğenen herkesin kullanımına sunabilirim.

Ben MVVM mimarisini kolayca kullanılmasını sağlayacak bir SDK üretmeyi amaçladım. Bu makaleyi, bu SDK’nın nasıl kullanılacağını açıklamak için hazırladım.

Kimler için

Benim gibi her yeni projesinde baştan kopyala yapıştır yapan ve MVVM mimarisini tercih eden herkes için.

Umarım özellikle yeni başlayanların bu SDK’yi kullanırken MVVM mimarisini daha kolay öğrenmesini sağlamış olurum.

Açıklama

MVVM mimarisi gereği 3 ayrı class ya da struct üzerinde şekillenir, doğal olarak SDK’de de bunlar mevcut:
• Model
• View
• ViewModel

Ve bunlara ek olarak SDK fazladan 2 extension içeriyor:
• NSObjectExtension (classların isimlerini döndüren bir NSObject extension’ı)
• ViewController+TapGesture (Herhangi bir ViewController’da boş alana dokununca klavyeyi kapatan ViewController extension’ı)

Dosya Yapısı

Dosya yapısı

Extensionlar

NSObjectExtension
Storyboard isimlerini string olarak elle girmek, daha sonra basit hatalara sebep olacağından bundan kaçmak için kullandığım bir yöntem. Özellikle, Storyboard ve UIViewController ya da UITableViewCell gibi classlarla aynı ismi paylaşan durumlarda kullanmak faydalı oluyor.
Kısacası, NSObject class’ından türemiş her class veya struct’ın adını string olarak geri döndürür.

ViewController+TapGesture
Hazırladığınız uygulamada, kullanıcı klavyeyi açtı, yazdı. Peki ya sonra? Boş alanlara tıklansa da klavye kapanmıyor, bunun çözümü için ben bu basit extension’ı kullanıyorum.

Klavyenin kapanması istenmeden öncesinde hideKeyboardWhenTappedAround() metodunun çağırılması lazım. Bunu garantiye almak için viewDidLoad‘ın altında çağırmak mantıklı geliyor.

override func viewDidLoad() {
super.viewDidLoad()
self.hideKeyboardWhenTappedAround()
}

kaynak: https://stackoverflow.com/a/27079103/14814820

Protocoller

BaseModelProtocol
İçinde kural barındırmayan tek protocol bu. Model struct’larında ortak olarak bulunması gerekir diyebileceğim bir özellik olmadığı için burası boş kaldı. Olası kurallar için yine de kaldırmadım.

BaseViewProtocol

BaseViewProtocol Screen Shot
BaseViewProtocol

MVVM mimarisinde bir view, ilgili viewModel’le etkileşimde olmalıdır. Bu durum her sayfa için geçerli olacağından BaseViewProtocol’e eklemek doğru olacaktır.

Bir de UI’lar farklı storyboardlarda tutulabileceği için.(Ben hepsini ayrı tutmak taraftarıyım zaten.) Burada karışıklık çıkmaması için; her view sınıfının, kendi storyboard ismini tutmasını zorunlu kıldım.

Get Emin Teyhan USLU’s stories in your inbox

Join Medium for free to get updates from this writer.

instantiate func

Press enter or click to view image in full size
BaseViewProtocol instantiate metodu

Bu extension sadece UIViewController’a conform edilen sınıflarda kullanılabilecektir. Bunu “where Self: UIViewController” ifadesi sayesinde kazanmış oldu.
Geri kalanının yeterince açık olduğunu düşünüyorum. Önce storyBoard, sonra da viewController oluşturuluyor. Ve referansı döndürülüyor.

BaseViewModelProtocol

BaseViewModelProtocol

MVVM mimarisinde bir viewModel, view ve model’le etkileşim içinde olmalıdır. O zaman bu diğer elemanları, viewModel’le ilişkilendirmek her durumda karşımıza çıkacağı için bu durumu BaseViewModelProtocol’le eklemek lazım diye düşündüm.

startPage func

BaseViewModelProtocol startPage fonksiyonu

Sayfa geçişlerinin hep viewModel içinde yönetilmesini tercih ettim. startPage extension’ı, başka bir sayfaya geçmek için kullanılıyor.
Kodları açıklamak gerekirse, öncelikle view’ın instantiate(BaseViewProtocol içindeki custom method, yukarıda açıklandı.) methodu çağırılır. Böylece view başlatılmış olur. ViewModel’in delegate’ine bu oluşturulan view’ın instance’ı atanır. İlgili viewController’ın viewModel property’sine, üzerinde çalıştığımız viewModel’in referansı atanır.
Uzun lafın kısası startPage metodu sayesinde, BaseProtocol’lerin içindeki propertie’lerin değerleri atanmış olur. <ViewModel>.delegate ve <ViewController>.viewModel

Örnek kullanım:

Press enter or click to view image in full size
Yeni sayfa başlatma örnek kullanımı

İlgili sayfanın startPage metodu çağırıldığında dönen viewController’ı navigationController’a push’lamak gerekiyor sadece.

Ben Nasıl Kullandım?

Herhangi bir sayfa oluşturulmadan önce sayfa adının sonuna Contract ifadesini eklediğim bir dosya açmayı ve tüm protocolleri burada toplamayı tercih ettim . O sayfaya dair her özelliği burada başlıklar halinde görebilecektim.(method adları ve bazı değişkenleri)

Press enter or click to view image in full size
Contract sayfası örneği

Her MVVM elemanı için yeni protocol oluşturdum. Örneğin DetailPageViewModelProtocol, bu protocol BaseViewModelProtol’i conform etmelidir. Ayrıca viewType’ı, hemen alttaki, DetailPageViewControllerProtocol ve ModelType’ı DetailPageModelProtocol olmalıdır diye belirttim. Bu bilgileri de where ifadesinden sonrasına ekleyerek ifade etmiş oldum.
Bunları yerleştirmem sayesinde BaseProtocol’lerin içindeki delegate veya viewModel gibi değişkenler buraya verdiğim protocolleri conform eden sınıflardan oluşturulmak zorundadır. Ayrıca burada olması çok daha derli toplu gözükmesini sağlıyor.
Her bir protocol’e ilgili sınıflarda fazladan olması gereken metotların adlarını ekliyorum.

Örnek: DetailPageViewModel Sınıfı

DetailPageViewModel conform edildikten sonrası

Sayfaya özel protocoller hazırlandıktan sonra, sıra bu protocolleri conform edecek sınıfları yazmakta.

Typealias ve değişkenlerin hazırlanma süreci

Bilindiği üzere bir protocol conform edilince protocol’ün şart koştuğu metodları xcode sayesinde o sınıfa ekleyebiliyorsunuz. typealias’ları yazdıktan sonra, burası için, ViewModel’in değişkenleri olan model ve delegate’in tipi de otomatikman belirlenmiş oluyor. xcode, sonradan bunları da eklememizi sağlıyor. İkinci tıklamayla hepsi hazır oluyor yani.

Sıra o sınıf için geriye kalan metotların içini doldurmaya kalıyor. Bu işlemler diğer elemanlar için de aynı şekilde devam ediyor.
Örneğin tamamı için: https://github.com/TeyUs/Sample_CoreData_MVVM

Sonuç

Kuralları net olan yerleri tekrar tekrar yazmak yerine her projenin başında BaseProtocolleri eklemek yeterli olacak.
Son zamanlarda yaptığım tüm küçük uygulamalarda kopyala yapıştır yapmaya başlamıştım, artık bundan kurtuldum.
Hem de beğenen herkesin kullanabileceğini bilmek çok mutlu ediyor.

SDK Nasıl Kullanılır

Bunun için paketi projeye eklemek gerekiyor.
File > Add Packages… > linki üstteki arama çubuğuna yapıştırın: https://github.com/TeyUs/MVVMBaseProtocols.git > Add Packages
Sonrasında benim gibi kullanırsanız o dosyanın başına “import MVVMBaseProtocols” yazdıktan sonra bu makale boyunca açıkladığım gibi kullanabilirsiniz.

DONE

--

--