Ana Sayfa / Blog / WidgetKit: Home Screen ve Lock Screen için tasarım prensibi

WidgetKit: Home Screen ve Lock Screen için tasarım prensibi

Widget tasarımı iOS app'ten farklı. 3 app'te widget ekledim, her seferinde farklı dersler. Timeline, relevance, size kararları.

Widget’lar iOS 14’te geldi, iOS 16’da Lock Screen’e de girdi. 3 app’imde widget ekledim. Her seferinde öğrendiğim bir şey vardı. En önemli ders: widget app değil, ama aynı kurallara uymuyor.

Bu yazıda widget tasarım prensiplerini, timeline provider mantığını ve relevance score kullanımını anlatacağım.

Widget app değildir

Yeni başlayanların en büyük hatası: widget’ı mini app sanmak. Widget tıklanamaz (Medium/Large’da açık deep link hariç), scrollable değil, real-time refresh yapamaz. Bir fotoğraf düşün.

Widget bir snapshot. Apple her birkaç dakikada bir görsel snapshot oluşturuyor ve home screen’de gösteriyor. Kullanıcı tıkladığında app açılıyor. Widget’ın kendisi interactivity yok (iOS 17’ye kadar).

iOS 17 ile interactive widget geldi: Button ve Toggle çalışıyor. Ama bu da sınırlı, widget’tan karmaşık interaction olmuyor.

Timeline provider nasıl çalışıyor?

Widget’ın kalbi TimelineProvider protocol. 3 metod:

placeholder(), Widget ilk yüklendiğinde gösterilen statik görünüm. Actual data yok, UI shell’i.

getSnapshot(), Widget gallery’de preview için. Fake/demo data ile hızlıca render edilecek görünüm.

getTimeline(), Asıl mantık burada. Bir dizi entry veriyorsun, her entry’nin bir tarihi var. iOS her tarihte widget’ı o entry’yle render ediyor.

Örnek bir timeline:

let now = Date()
let entries = [
    SimpleEntry(date: now, data: currentData),
    SimpleEntry(date: now.addingTimeInterval(3600), data: nextHourData),
    SimpleEntry(date: now.addingTimeInterval(7200), data: twoHoursData),
]
let timeline = Timeline(entries: entries, policy: .atEnd)

policy: .atEnd, son entry’nin süresi bittikten sonra yeni timeline iste.
policy: .after(date), belirli tarihte yeni timeline iste.
policy: .never, manual reload edene kadar bir daha isteme.

Widget refresh ne kadar sık?

Bu yeni başlayanların sık karşılaştığı sürpriz: widget’ın kendi refresh frequency’si yok. Siz timeline’da ne zaman refresh isterseniz o zaman refresh yapılır.

Ama Apple sınır koyuyor:

  • Typical: 5-10 dakikada bir refresh yeter. Haber widget’ı, hava durumu gibi.
  • Energy budget: Apple günde widget’a belirli bir refresh bütçesi veriyor. Çok sık isterseniz görmezden gelir.
  • Real-time imkansız. Canlı fiyat, canlı score gösteren widget yapamıyorsun. Her saniye refresh olmuyor.

En iyi strateji: 1 saat ileriye entry’leri pre-generate et, iOS kendi render’lıyor. Refresh budget’ını minimize et.

Widget size’lar ve tasarım

iOS widget’ları üç ana boyutta geliyor:

systemSmall: 1×1 grid, ~158×158 pt. Tek bilgi veya basit stat göster. Tıklama tek deep link’e gidiyor.

systemMedium: 2×2 grid yerleşimi. Biraz daha zengin. Hala tek tıklama.

systemLarge: 2×4 grid. En detaylı görünüm. Multiple tappable areas (iOS 17+ Link with SwiftUI).

iOS 16+ Lock Screen widget’ları:

accessoryCircular: Dairesel, tek metric. “Ring fill” gösterir gibi.

accessoryRectangular: Kısa, 1 satır bilgi.

accessoryInline: Saat barında tek satır text.

Dentii’de 4 farklı widget size support’u kurdum. Her biri farklı kullanım case’i:

  • Small: Bugünkü brushing status (yapıldı/yapılmadı)
  • Medium: Son 7 günün consistency grafiği
  • Circular (lock screen): Günlük streak sayısı
  • Rectangular (lock screen): “Akşam fırçalaman” reminder text

Relevance score (Smart Stack)

iOS Smart Stack otomatik widget rotation yapıyor. Hangi widget en tepeye gelecek? Relevance score belirliyor.

Timeline entry’ye relevance eklerseniz, iOS bunu kullanıyor:

let entry = SimpleEntry(
    date: Date(),
    data: currentData,
    relevance: TimelineEntryRelevance(score: 0.8, duration: 600)
)

score: 0-1 arası. 1 = çok önemli.
duration: Bu relevance score’un kaç saniye geçerli olacağı.

Snoozio’da sleep reminder widget’ı geceye doğru relevance artıyor (0.3 → 0.9). Smart Stack gece 22:00 civarında bunu en tepeye alıyor.

Kullanıcı widget’a tıkladığında Smart Stack bunu “öğreniyor” ve bir sonraki benzer bağlamda daha sık gösteriyor.

Deep link handling

Widget’a tıklayınca kullanıcı app’te doğru yere gitmeli. Widget’ta SwiftUI Link kullanıyorsun:

Link(destination: URL(string: "myapp://dashboard")!) {
    Text("Dashboard")
}

App tarafında URL scheme handler:

.onOpenURL { url in
    if url.host == "dashboard" {
        navigationPath.append(.dashboard)
    }
}

iOS 17+’de widget içinde Button kullanabilirsin, ama sadece AppIntent ile çalışıyor. Genellikle Link daha basit.

Tasarım disiplini

Widget tasarımı için önemli kurallar:

1. Tek bir bilgi odaklan. Small widget’ta 5 farklı şey gösterirsen hiçbiri okunmuyor.

2. Text’leri büyük tut. Minimum 14pt, ideal 16-18pt. Küçük text okunamıyor.

3. Contrast yüksek. Home screen’de farklı wallpaper’lar var. Background opacity düşük + güçlü contrast’lı text.

4. Loading/error state’leri unutma. “Veri yükleniyor” veya “Bağlantı yok” durumları için placeholder. Boş widget kötü bir UX.

5. Dark Mode test. Light ve dark wallpaper’ların ikisinde de güzel görünmeli.

Widget’ın limit’leri

Bu noktaları kullanıcılara açıklamak gerekebilir:

  • Gerçek zamanlı veri yok. 5 dakika eski bir snapshot görüyorsun.
  • Network call async işliyor. Widget load’unda sync network yok.
  • Keychain’e erişim sınırlı. Widget ayrı process’te çalıştığı için app keychain’ine app group ile share etmelisin.
  • Shared data için App Group. UserDefaults, Core Data, File system paylaşımı için App Group gerekli.

Test etmek

Widget test’i simulator’da kolay ama real device’da daha doğru sonuç veriyor. Test stratejim:

  1. Widget gallery preview. Ilk launch’ta widget’ı add ettiğinde gördüğün şey.
  2. Her size için design preview. Small, medium, large hepsini dene.
  3. Lock Screen widget iOS 16+ real device’da test et.
  4. Dark mode toggle ve farklı wallpaper’lar.
  5. Deep link widget tıklandıktan sonra doğru ekrana gidiyor mu?
  6. Refresh testing. 24 saat widget’ı gözlem, timeline doğru refresh ediyor mu?

Sonuç

Widget’lar app’inin “daima görünen” uzantısı. Doğru tasarlanmış bir widget kullanıcıya her home screen açtığında değer sunuyor, app açmasına gerek kalmıyor. Ama app olmadığı için kuralları farklı: statik, periyodik, tek-odaklı.

İlk widget projenizde küçük başlayın. Small size, tek bilgi, 1 saat refresh interval. Sonra ihtiyaç doğdukça genişletin. Karmaşık widget yapmak kolay, iyi widget yapmak zor.

Bu konuda bir projeniz mi var?

Kısa bir özet bırakın, 24 saat içinde size dönüş yapayım.

İletişime Geç