watchOS 9 (2022) Apple’ın Apple Watch app mimarisi için büyük bir geçiş. Eski “WatchKit extension” yaklaşımı deprecate edildi, yeni “watchOS app” target’ı standart oldu.
İki Apple Watch app’imi (Dentii ve Snoozio) bu yeni mimariye migrate ettim. Her birinde farklı sürprizler çıktı. Bu yazıda migration deneyimini ve dikkat edilmesi gerekenleri anlatacağım.
Eski ve yeni arasındaki fark
Eski WatchKit Extension yaklaşımı:
– Xcode’da iOS app + Watch App + Watch Extension olmak üzere 3 target
– Watch App: UI files (storyboard)
– Watch Extension: executable code
– Bu ayrım watchOS 1-6 için mantıklıydı: Watch’ta code çalışmıyordu, sadece iPhone’da çalışan Extension UI update ediyordu
Yeni watchOS App yaklaşımı:
– Xcode’da iOS app + Watch App target (tek target)
– UI + code tek binary’de
– Native watchOS target, bağımsız çalışıyor
Apple watchOS 6+’dan native watchOS app tanıtmıştı ama eski yaklaşım da destekleniyordu. watchOS 9 ile eski yaklaşım deprecated.
Neden migrate etmek gerekli?
Sadece Apple’ın yönlendirmesi değil:
- Yeni watchOS feature’ları sadece native target’ta çalışıyor. Always On display, WidgetKit complications, new SwiftUI API’lar.
- Build performansı daha iyi. Tek target demek daha az overhead.
- Debugging kolay. Extension debugging bazen çok karmaşık oluyordu.
- App Store Connect submission daha sade. Eski sistemde bazen Watch extension ayrı review sürecine giriyordu.
Eğer eski mimariyle kalırsan: yeni feature’ları kullanamıyorsun, bir süre sonra Xcode support bile kesilebilir.
Migration adımları
Dentii’de yaptığım migration sıralaması:
Adım 1: Xcode’da yeni target oluştur.
File > New > Target > Watch App. Xcode otomatik olarak yeni mimariyle target ekler. Eski Extension target’ı silmeden, coexist ediyor.
Adım 2: Eski Watch App’ten UI’ı taşı.
Eski target’ta storyboard varsa, SwiftUI’ya çevir. watchOS 7+ SwiftUI yeterli. Storyboard desteği hâlâ var ama gelecek için SwiftUI.
Adım 3: Kodu taşı.
Eski Extension target’ındaki Swift dosyalarını yeni target’a kopyala. InterfaceController gibi eski WatchKit class’ları yok, doğrudan SwiftUI view’lar.
Adım 4: WatchConnectivity logic’i revisit et.
WCSession setup ve delegate’ler aynı kalıyor. Ama message sending bazı edge case’lerde değişmiş. Test et.
Adım 5: Complication’ları migrate et.
Eski CLKComplicationDataSource artık deprecated. WidgetKit ile yeniden yaz. Bu en zorlu kısım çünkü UI tamamen yeniden.
Adım 6: Eski Extension target’ını sil.
Her şey çalışıyorsa eski target’ı sil. Cleanup.
Toplam süre: Dentii’de 4 gün, Snoozio’da 3 gün. Code base’inin büyüklüğüne bağlı.
Karşılaştığım 3 sürpriz
Sürpriz 1: Complication API tamamen yeni
Eski CLKComplication mimarisi:
– CLKComplicationDataSource protocol
– Multiple family support (utilitarianSmall, modularSmall, etc.)
– CLKComplicationTemplate subclass’ları
– getCurrentTimelineEntry callback’i
Yeni WidgetKit mimarisi:
– TimelineProvider protocol
– WidgetFamily enum
– SwiftUI view tree
– getTimeline() function
Kavramsal olarak benzer ama syntax tamamen değişik. Complication’larımı sıfırdan yeniden yazdım. 1 günlük iş.
Sürpriz 2: Background refresh behavior
Eski Watch Extension background’da bazı constraint’lerle çalışıyordu. Yeni watchOS app’te:
– Background refresh eventi BGTaskScheduler yerine custom WKApplicationRefreshBackgroundTask
– Sıklık Apple tarafından daha agresif sınırlanıyor
– Battery impact daha katı hesaplanıyor
Dentii’de her brushing session için background refresh plantım vardı. Yeni mimaride refresh sıklığı düştü. User experience biraz değişti, battery ile trade-off olarak kabul ettim.
Sürpriz 3: iOS companion app iletişimi
WCSession API aynı ama edge case’lerde davranış farklı. Özellikle:
– sendMessage sıklığı
– transferUserInfo delay’leri
– updateApplicationContext timing’leri
Bazı message’lar beklediğimden geç iletilmeye başladı. Test coverage’ını genişlettim. 2-3 saatlik debug süreci.
Apple Watch Always On display
Yeni watchOS app target’ında Always On display native destek var. Watch bileğin aşağıda olsa bile ekran aktif, düşük parlaklıkta:
ContentView()
.onChange(of: scenePhase) { _, newPhase in
if newPhase == .inactive {
// Always On mode
}
}Dentii’de brushing timer ekranı Always On’da düşük parlaklıkta countdown gösteriyor. Kullanıcı watch’a her bakmak zorunda kalmıyor. Bu feature eski mimaride yoktu.
WidgetKit complications tasarımı
Yeni WidgetKit ile 6 farklı widget family support ediliyor:
.accessoryCorner– dairesel çevredeki köşe.accessoryCircular– dairesel complications.accessoryRectangular– dikdörtgen 1 satır.accessoryInline– saat barında 1 satır text
Her biri ayrı SwiftUI view. Hepsini destekle:
struct MyComplication: Widget {
var body: some WidgetConfiguration {
StaticConfiguration(kind: "MyComplication", provider: Provider()) { entry in
ComplicationView(entry: entry)
}
.supportedFamilies([.accessoryCircular, .accessoryCorner, .accessoryRectangular, .accessoryInline])
}
}Her family için ayrı case handle etmen gerekiyor UI tarafında.
Migration sonrası test
Real device’da bol bol test:
- App launch time. Eski vs yeni launch süresi karşılaştır.
- Complication refresh. Watch face’te saat boyunca güncel kalıyor mu?
- WCSession message delivery. iPhone’dan watch’a data gidiyor mu?
- Background wake. App background’dayken refresh event geliyor mu?
- Memory usage. Watch CPU zayıf, memory pressure olmamalı.
- Battery impact. 1 günlük kullanım sonrası watch battery eski ile yeni versiyon farkı?
Bu listeyi geçtikten sonra App Store submission’a hazır.
Production gotchas
Migration’dan sonra dikkat ettiğim şeyler:
- Old app version eski mimariyle kalıyor. Kullanıcılar yeni update’i indirene kadar eski mimari çalışıyor olacak. Coexist ediyor.
- Watch app auto-install. iOS app install edildiğinde eğer Apple Watch varsa watch app otomatik kuruluyor. Bu davranış yeni mimaride daha güvenilir.
- App Store Connect config. Watch app’i yeni target’ta define ettiğinde, iOS app binary’sinin içine gömülüyor. Ayrı bundle değil.
Sonuç
watchOS app migration’ı kaçınılmaz bir iş. Apple eski WatchKit mimarisini yavaşça gömecek. 3-5 günlük bir work investment ama sonrası için Always On, native WidgetKit complications, better performance kazanıyorsunuz.
Eğer Apple Watch app’iniz varsa ve hâlâ eski mimaride kalıyorsanız, migration’ı 2025 yılı planına ekleyin. Sonraki watchOS version’ları yeni feature’ları sadece new target’a ekleyecek.