Tüm Yazılar
KategoriiOS
Okuma Süresi
14 dk okuma
Yayın Tarihi
...
Kelime Sayısı
2.599kelime

Kahveni hazırla - bu içerikli bir makale!

TipKit framework ile non-intrusive in-app tooltips, rules engine, eligibility tracking, event-based display ve analytics — onboarding UX devrimi.

TipKit: iOS Onboarding ve Feature Discovery Pattern Rehberi 2026

# TipKit: iOS Onboarding ve Feature Discovery Pattern Rehberi 2026

Kullanıcılar uygulamanızın en güçlü özelliklerini hiç keşfetmeyebilir. Klasik onboarding carousel'ları okuma oranı %20'nin altında. Push notification "yeni özellik" bildirimleri ignore ediliyor. TipKit, bu soruna Apple'ın cevabı: doğru anda, doğru bağlamda, non-intrusive tooltip'ler.

iOS 17 ile gelen TipKit, 2026'da iOS 19 desteğiyle birlikte production-grade bir onboarding framework'e dönüştü. Bu yazı framework'ün tüm katmanlarını, edge case'leri ve Human Interface Guidelines uyumunu ele alıyor.

💡 Pro Tip: TipKit'in en güçlü yanı "rules engine." Kullanıcı uygulamayı 3 kez açmış, ama o özelliği hiç kullanmamışsa göster. Bu tür bağlamsal mantık başka hiçbir framework'te bu kadar kolay değil.

İçindekiler


TipKit Nedir ve Neden Farklı?

Geleneksel onboarding yöntemlerinin sorunları:

  • Carousel/walkthrough:: Kullanıcı henüz o özelliğe ihtiyaç duymadan gösterilir
  • Overlay coach marks:: Tüm UI'ı bloke eder, kullanıcı stres yaşar
  • Push notification:: Uygulama dışı, bağlam yok
  • Alert dialog:: Modal — kullanıcı "dismiss" der, öğrenmez

TipKit'in yaklaşımı: Just-in-time feature discovery. Kullanıcı o özelliğe yakın bir bağlamdayken, onu bloke etmeden göster.

Teknik olarak TipKit:

  • Rules engine ile eligibility hesaplar
  • Gösterim geçmişini persist eder (bir kez gösterilen bir daha gösterilmez, varsayılan)
  • SwiftUI ve UIKit her ikisini destekler
  • iCloud sync ile cihazlar arası durum senkronizasyonu sağlar (opsiyonel)
  • Test modunda tüm tip'leri sıfırlayabilirsiniz

Tips.configure() ve İlk Kurulum

TipKit'in ilk kurulumu minimal. @main struct'ta veya App body'sinde çağrılmalı.

swift
1import TipKit
2import SwiftUI
3 
4@main
5struct UygulamApp: App {
6 
7 init() {
8 configureTipKit()
9 }
10 
11 var body: some Scene {
12 WindowGroup {
13 AnaSayfa()
14 }
15 }
16 
17 private func configureTipKit() {
18 do {
19 // Varsayılan konfigürasyon
20 try Tips.configure([
21 .displayFrequency(.immediate), // Sıklık kontrolü
22 .datastoreLocation(.applicationDefault) // Persist yeri
23 ])
24 } catch {
25 // TipKit başlatamazsa uygulamayı çökertme
26 print("TipKit konfigürasyon hatası: \(error)")
27 }
28 }
29}
30 
31// Test modunda tüm tip'leri sıfırla
32#if DEBUG
33extension Tips {
34 static func resetForTesting() {
35 try? Tips.resetDatastore()
36 }
37}
38#endif

Konfigürasyon seçenekleri:

swift
1// Gösterim sıklığı
2.displayFrequency(.immediate) // Hemen göster
3.displayFrequency(.hourly) // Saatte bir
4.displayFrequency(.daily) // Günde bir
5.displayFrequency(.weekly) // Haftada bir
6.displayFrequency(.monthly) // Ayda bir
7 
8// Datastore konumu
9.datastoreLocation(.applicationDefault) // Uygulama container'ı
10.datastoreLocation(.groupContainer("group.sirket.uygulama")) // App Group (widget)
11.datastoreLocation(.url(customURL)) // Özel konum

Tip Protocol: Tanımlama Yöntemi

Her tip, Tip protokolüne uyan bir struct veya class. Minimum gereksinimler: title.

swift
1import TipKit
2 
3// Minimum tip tanımı
4struct YeniOzellikTip: Tip {
5 var title: Text {
6 Text("Hızlı Arama")
7 }
8}
9 
10// Tam tip tanımı
11struct FavorilerTip: Tip {
12 var title: Text {
13 Text("Favorilere Ekle")
14 }
15 
16 var message: Text? {
17 Text("Sık kullandığın içerikleri kaydet, hızla ulaş.")
18 }
19 
20 var image: Image? {
21 Image(systemName: "star.fill")
22 }
23 
24 // Özel ID (varsayılan: type adı)
25 var id: String {
26 return "com.sirket.uygulama.favoriler-tip-v2"
27 }
28 
29 // Maksimum gösterim sayısı
30 var options: [any TipOption] {
31 [MaxDisplayCount(3)]
32 }
33}
34 
35// Çok adımlı özellik tanıtımı
36struct CokAdimliTip: Tip {
37 var title: Text {
38 Text("3 adımda tamamla")
39 }
40 
41 var message: Text? {
42 Text("Profil, tercihler, bildirimler. Hepsini şimdi ayarla.")
43 }
44 
45 var actions: [Action] {
46 [
47 Action(id: "basla", title: "Başla"),
48 Action(id: "sonra", title: "Daha Sonra")
49 ]
50 }
51}

@Parameter ve Durum Yönetimi

@Parameter ile tip'lerin durum değişkenlerini persist edebilirsiniz. Bu rules engine'in temel taşı.

swift
1struct GelismisFiltresTip: Tip {
2 
3 // @Parameter — TipKit tarafından persist edilir
4 @Parameter
5 static var kullaniciBronzSeviyeUlasti: Bool = false
6 
7 @Parameter
8 static var filtreKullanimiSayisi: Int = 0
9 
10 var title: Text {
11 Text("Gelişmiş Filtreler")
12 }
13 
14 var message: Text? {
15 Text("Aramalarını daha da hassaslaştır. Fiyat, konum, puan filtreleri.")
16 }
17 
18 // Bu parameter'lar başka yerden güncellenebilir
19 // Tip otomatik olarak yeniden değerlendirilir
20 var rules: [Rule] {
21 [
22 #Rule(Self.$kullaniciBronzSeviyeUlasti) { $0 == true },
23 #Rule(Self.$filtreKullanimiSayisi) { $0 >= 2 }
24 ]
25 }
26}
27 
28// ViewModel içinde parameter güncelleme
29class UrunListesiViewModel: ObservableObject {
30 
31 func filtreUygula() {
32 // İş mantığı
33 GelismisFiltresTip.filtreKullanimiSayisi += 1
34 
35 // Koşul sağlandıysa TipKit otomatik değerlendirir
36 if kullanici.seviye == .bronz {
37 GelismisFiltresTip.kullaniciBronzSeviyeUlasti = true
38 }
39 }
40}

Rules Engine: Koşullu Gösterim

TipKit'in en güçlü özelliği: declarative rules. Birden fazla koşul AND/OR ile birleştirilebilir.

swift
1struct ProOzellikTip: Tip {
2 
3 @Parameter
4 static var proUyeOldu: Bool = false
5 
6 @Parameter
7 static var anaSayfaGoruntulenmeSayisi: Int = 0
8 
9 var title: Text {
10 Text("Pro Özellik: Toplu Dışa Aktar")
11 }
12 
13 var message: Text? {
14 Text("Tüm verini tek tıkla CSV veya PDF olarak dışa aktar.")
15 }
16 
17 // Rules — tüm koşullar sağlanmalı (AND logic)
18 var rules: [Rule] {
19 [
20 // Pro üye olmalı
21 #Rule(Self.$proUyeOldu) {
22 $0 == true
23 },
24 // Ana sayfayı en az 5 kez görüntülemiş olmalı
25 #Rule(Self.$anaSayfaGoruntulenmeSayisi) {
26 $0 >= 5
27 }
28 ]
29 }
30 
31 var options: [any TipOption] {
32 // Bu tip en fazla 1 kez gösterilsin
33 [MaxDisplayCount(1)]
34 }
35}
36 
37// Tarih bazlı rule — süreli kampanya
38struct KampanyaTip: Tip {
39 
40 @Parameter
41 static var kampanyaBasladiMi: Bool = false
42 
43 var title: Text {
44 Text("Yaz Kampanyası Başladı!")
45 }
46 
47 var rules: [Rule] {
48 [
49 #Rule(Self.$kampanyaBasladiMi) { $0 == true }
50 ]
51 }
52 
53 var options: [any TipOption] {
54 // 7 gün sonra otomatik invalidate
55 [IgnoresDisplayFrequency(true)]
56 }
57}

Eligibility Tracking: Event-Based Display

Event-based display, kullanıcı davranışlarına göre tip gösterimi için en güçlü mekanizma.

swift
1struct AramaGecikmesiTip: Tip {
2 
3 // Event tracking
4 static let aramaTamamlandi = Event(id: "arama-tamamlandi")
5 
6 var title: Text {
7 Text("Arama Geçmişi")
8 }
9 
10 var message: Text? {
11 Text("Son aramalarına tek dokunuşla ulaş.")
12 }
13 
14 var rules: [Rule] {
15 [
16 // Kullanıcı en az 3 arama yapmış olmalı
17 #Rule(Self.aramaTamamlandi) {
18 $0.donations.count >= 3
19 }
20 ]
21 }
22}
23 
24// Ekranda event donation
25struct AramaEkrani: View {
26 let aramaGecmisi: AramaGecikmesiTip = .init()
27 
28 var body: some View {
29 VStack {
30 SearchBar { sorgu in
31 aramaYap(sorgu: sorgu)
32 // Event donate et
33 Task {
34 await AramaGecikmesiTip.aramaTamamlandi.donate()
35 }
36 }
37 
38 TipView(aramaGecmisi)
39 }
40 }
41}
42 
43// Özel donation içeriği
44struct KarmasikEventTip: Tip {
45 
46 struct OturumBilgisi: Codable {
47 var sure: TimeInterval
48 var kategori: String
49 }
50 
51 static let uzunOturumGerceklesti = Event(id: "uzun-oturum")
52 
53 var rules: [Rule] {
54 [
55 #Rule(Self.uzunOturumGerceklesti) { event in
56 // Son 7 günde 5 dakika+ oturum en az 3 kez
57 let yediGunOnce = Date().addingTimeInterval(-7 * 24 * 3600)
58 let yakinOturumlar = event.donations.filter { $0.date > yediGunOnce }
59 return yakinDonations.count >= 3
60 }
61 ]
62 }
63}

TipView vs popoverTip: Ne Zaman Hangisi?

İki farklı gösterim modu var ve ikisinin de doğru kullanım senaryosu farklı.

swift
1// TipView — inline, tam alan kaplayan kart
2struct FavoriListesiEkrani: View {
3 let favoriEklemeTip = FavoriEklemeTip()
4 
5 var body: some View {
6 List(urunler) { urun in
7 UrunSatiri(urun: urun)
8 }
9 .safeAreaInset(edge: .bottom) {
10 // Alt kısımda inline tip
11 TipView(favoriEklemeTip, arrowEdge: .bottom)
12 .padding()
13 }
14 }
15}
16 
17// popoverTip — spesifik UI elementi üzerinde
18struct AramaButonu: View {
19 let aramaKisayolTip = AramaKisayolTip()
20 
21 var body: some View {
22 Button(action: aramaAc) {
23 Image(systemName: "magnifyingglass")
24 }
25 // Buton üzerinde popover
26 .popoverTip(aramaKisayolTip, arrowEdge: .top)
27 }
28}
29 
30// Ne zaman hangisi?
31// TipView:
32// - Genel, tam sayfa öneri
33// - "Bu sayfada bir şey var" bildirimi
34// - Daha uzun açıklama metni
35// - Aksiyon butonları gerektiğinde
36 
37// popoverTip:
38// - Spesifik bir UI elementini işaret etmek için
39// - "Bu buton ne yapar?" açıklaması
40// - Kısa, öz mesaj
41// - Toolbar, tab bar, navigation item için ideal

Actions: learnMore ve dismiss

Tip'lere aksiyon butonları ekleyebilirsiniz. Varsayılan davranış: aksiyon tıklandığında tip invalidate olur.

swift
1struct TutorialTip: Tip {
2 
3 var title: Text {
4 Text("Nasıl kullanılır?")
5 }
6 
7 var message: Text? {
8 Text("İlk kez mi kullanıyorsunuz? Hızlı başlangıç rehberimize göz atın.")
9 }
10 
11 // Özel aksiyonlar
12 var actions: [Action] {
13 [
14 // Birincil aksiyon
15 Action(
16 title: "Rehberi Gör",
17 style: .primary // iOS 17.2+
18 ),
19 // İkincil aksiyon
20 Action(
21 title: "Atla",
22 style: .default
23 )
24 ]
25 }
26}
27 
28// Aksiyon handler'ı
29struct AnaEkrani: View {
30 @State private var rehberGoruluyor = false
31 let tutorialTip = TutorialTip()
32 
33 var body: some View {
34 NavigationStack {
35 IcerikGorunumu()
36 .safeAreaInset(edge: .top) {
37 TipView(tutorialTip) { aksiyon in
38 switch aksiyon.id {
39 case "rehberi-goster":
40 rehberGoruluyor = true
41 // TipKit otomatik invalidate eder
42 case "atla":
43 // Tip geçersiz kıl
44 tutorialTip.invalidate(reason: .actionPerformed)
45 default:
46 break
47 }
48 }
49 }
50 }
51 .sheet(isPresented: $rehberGoruluyor) {
52 RehberGorunumu()
53 }
54 }
55}

Custom Styling: TipViewStyle

Varsayılan TipKit görünümü Apple'ın standart tasarımını kullanır. Markanıza uydurmak için TipViewStyle protokolü.

swift
1// Özel stil tanımı
2struct MarkaTipStili: TipViewStyle {
3 
4 func makeBody(configuration: Configuration) -> some View {
5 HStack(alignment: .top, spacing: 12) {
6 // Özel ikon
7 if let image = configuration.image {
8 image
9 .resizable()
10 .frame(width: 36, height: 36)
11 .foregroundStyle(.white)
12 .padding(8)
13 .background(
14 LinearGradient(
15 colors: [Color.markaMAvi, Color.markaCyan],
16 startPoint: .topLeading,
17 endPoint: .bottomTrailing
18 )
19 )
20 .clipShape(RoundedRectangle(cornerRadius: 8))
21 }
22 
23 VStack(alignment: .leading, spacing: 4) {
24 configuration.title
25 .font(.headline)
26 .foregroundStyle(.primary)
27 
28 configuration.message?
29 .font(.subheadline)
30 .foregroundStyle(.secondary)
31 .multilineTextAlignment(.leading)
32 
33 // Aksiyonlar
34 HStack {
35 ForEach(configuration.actions) { aksiyon in
36 Button(aksiyon.title) {
37 aksiyon.perform()
38 }
39 .buttonStyle(.bordered)
40 .tint(Color.markaMAvi)
41 }
42 }
43 .padding(.top, 4)
44 }
45 
46 Spacer()
47 
48 // Kapatma butonu
49 Button {
50 configuration.tip.invalidate(reason: .tipClosed)
51 } label: {
52 Image(systemName: "xmark.circle.fill")
53 .foregroundStyle(.tertiary)
54 }
55 }
56 .padding()
57 .background(.regularMaterial)
58 .clipShape(RoundedRectangle(cornerRadius: 16))
59 .shadow(color: .black.opacity(0.08), radius: 8, x: 0, y: 4)
60 }
61}
62 
63// Kullanım
64TipView(tip)
65 .tipViewStyle(MarkaTipStili())
66 
67// App genelinde varsayılan stil
68struct UygulamApp: App {
69 var body: some Scene {
70 WindowGroup {
71 AnaSayfa()
72 .tipViewStyle(MarkaTipStili())
73 }
74 }
75}

Analytics: tipStatusUpdated

Hangi tip'lerin gösterildiğini, hangilerinin dismiss edildiğini, hangi aksiyonların tıklandığını takip etmek için Tips.tipStatusUpdated publisher.

swift
1import TipKit
2import Combine
3 
4class TipAnalyticsServisi: ObservableObject {
5 private var iptal = Set<AnyCancellable>()
6 
7 init() {
8 dinle()
9 }
10 
11 private func dinle() {
12 Tips.tipStatusUpdated
13 .sink { [weak self] guncelleme in
14 self?.isleTipGuncellemesi(guncelleme)
15 }
16 .store(in: &iptal)
17 }
18 
19 private func isleTipGuncellemesi(_ guncelleme: Tips.TipStatusUpdate) {
20 let tipID = guncelleme.tip.id
21 
22 switch guncelleme.status {
23 case .available:
24 // Tip kullanıcıya gösterildi
25 Analytics.gonderOlay("tip_shown", parametreler: [
26 "tip_id": tipID,
27 "timestamp": Date().timeIntervalSince1970
28 ])
29 
30 case .invalidated(let neden):
31 switch neden {
32 case .actionPerformed:
33 Analytics.gonderOlay("tip_action_performed", parametreler: [
34 "tip_id": tipID
35 ])
36 case .tipClosed:
37 Analytics.gonderOlay("tip_dismissed", parametreler: [
38 "tip_id": tipID
39 ])
40 case .displayCountExceeded:
41 Analytics.gonderOlay("tip_max_display_reached", parametreler: [
42 "tip_id": tipID
43 ])
44 case .displayDurationExceeded:
45 Analytics.gonderOlay("tip_duration_exceeded", parametreler: [
46 "tip_id": tipID
47 ])
48 @unknown default:
49 break
50 }
51 
52 @unknown default:
53 break
54 }
55 }
56}

Localization ve A/B Testing

TipKit'te localization Text view ile doğrudan, standart SwiftUI localization pattern'ı izler.

swift
1// Strings catalog ile localization
2struct PaylasTip: Tip {
3 
4 var title: Text {
5 // Localizable.xcstrings veya Strings catalog'dan çeker
6 Text("tip.share.title", bundle: .main)
7 }
8 
9 var message: Text? {
10 Text("tip.share.message", bundle: .main)
11 }
12}
13 
14// A/B Testing — @Parameter ile variant kontrolü
15struct OnboardingTip: Tip {
16 
17 @Parameter
18 static var abVariant: String = "A"
19 
20 var title: Text {
21 switch Self.abVariant {
22 case "A":
23 return Text("Hızlı Başlangıç Rehberi")
24 case "B":
25 return Text("3 Dakikada Ustalaşın")
26 default:
27 return Text("Başlayın")
28 }
29 }
30 
31 var message: Text? {
32 switch Self.abVariant {
33 case "A":
34 return Text("Tüm özellikleri adım adım keşfedin.")
35 case "B":
36 return Text("En sık kullanılan 5 özelliği hemen öğrenin.")
37 default:
38 return nil
39 }
40 }
41}
42 
43// App launch'ta A/B assignment
44struct UygulamApp: App {
45 
46 init() {
47 try? Tips.configure()
48 
49 // Remote config'den veya local mantıktan variant ata
50 let variant = RemoteKonfigurasyon.tipABVariant ?? (Int.random(in: 0...1) == 0 ? "A" : "B")
51 OnboardingTip.abVariant = variant
52 }
53}

Tip Versioning

Tip içeriği değiştiğinde ID güncellenmeli, aksi takdirde eski kullanıcılar güncellenmiş tip'i görmez.

swift
1// v1 — eski
2struct DisaAktarTipV1: Tip {
3 var id: String { "disaaktar-tip-v1" }
4 var title: Text { Text("Dışa Aktar") }
5}
6 
7// v2 — içerik değişti, yeni ID
8struct DisaAktarTipV2: Tip {
9 var id: String { "disaaktar-tip-v2" }
10 
11 var title: Text {
12 Text("Dışa Aktar — Yeni: PDF Desteği")
13 }
14 
15 var message: Text? {
16 Text("Artık PDF, CSV ve Excel formatında dışa aktarabilirsiniz.")
17 }
18}
19 
20// Versioning convention önerisi:
21// "sirket.uygulama.ozellik-v{MAJOR}"
22// Major versiyon sadece içerik değişiminde artır
23// Bug fix / typo düzeltme için artırmaya gerek yok

Edge Case'ler: Rapid Show/Hide

Hızlı ekran geçişlerinde tip'lerin anlık gösterilip gizlenmesi (flicker) yaygın bir sorun.

swift
1// Sorun: NavigationStack pop/push sırasında tip titriyor
2struct SorunluEkran: View {
3 let tip = BirSeylerTip()
4 
5 var body: some View {
6 List(urunler) { urun in
7 NavigationLink(destination: UrunDetay(urun: urun)) {
8 UrunSatiri(urun: urun)
9 }
10 }
11 .safeAreaInset(edge: .bottom) {
12 TipView(tip) // Navigate edilirken kaybolup geri geliyor
13 }
14 }
15}
16 
17// Çözüm: transition ile yumuşat
18struct DuzeltilmisEkran: View {
19 let tip = BirSeylerTip()
20 @State private var tipGoruldu = false
21 
22 var body: some View {
23 List(urunler) { urun in
24 NavigationLink(destination: UrunDetay(urun: urun)) {
25 UrunSatiri(urun: urun)
26 }
27 }
28 .safeAreaInset(edge: .bottom) {
29 TipView(tip)
30 .transition(.move(edge: .bottom).combined(with: .opacity))
31 .animation(.easeInOut(duration: 0.3), value: tipGoruldu)
32 }
33 .onAppear {
34 withAnimation {
35 tipGoruldu = true
36 }
37 }
38 .onDisappear {
39 tipGoruldu = false
40 }
41 }
42}
43 
44// Tab switching edge case — her tab'da farklı tip
45struct TabKonteyner: View {
46 @State private var secilenTab = 0
47 
48 var body: some View {
49 TabView(selection: $secilenTab) {
50 AnaEkrani()
51 .tabItem { Label("Ana Sayfa", systemImage: "house") }
52 .tag(0)
53 
54 AramaEkrani()
55 .tabItem { Label("Ara", systemImage: "magnifyingglass") }
56 .tag(1)
57 }
58 // NOT: popoverTip tab item üzerinde çalışmaz — bunun yerine
59 // overlay ile konumlandır
60 .overlay(alignment: .bottom) {
61 if secilenTab == 1 {
62 GeometryReader { geo in
63 TipView(AramaKisayolTip())
64 .position(x: geo.size.width * 0.75, y: geo.size.height - 80)
65 }
66 }
67 }
68 }
69}

Human Interface Guidelines Uyumu

Apple'ın HIG'i TipKit kullanımı için net kurallar belirliyor.

Yapılacaklar:

  1. Maksimum 3 tip'i aynı anda gösterme — kullanıcıyı bunaltma
  2. Tip'ler kritik işlem sırasında gösterilmemeli (form doldurma, ödeme)
  3. Her tip bağımsız bir özelliği açıklamalı — birden fazla şey anlatma
  4. Aksiyon butonları somut ve kısa olmalı ("Göster", "Dene" gibi)
  5. Kapatma her zaman açık olmalı — kullanıcı kontrolü şart

Yapılmayacaklar:

  1. Tip'i reklam / promosyon için kullanma
  2. Uygulama launch'ında önce tip gösterme — kullanıcının bağlamı yok
  3. İnce yazı veya küçük ikon kullanma — minimum 44pt touch target
  4. Koyu/açık mod dışı custom renk kullanımı — .regularMaterial kullan
swift
1// HIG uyumlu tip tasarımı
2struct HIGUyumluTip: Tip {
3 
4 var title: Text {
5 // Kısa, eylem odaklı
6 Text("Listeyi Paylaş")
7 }
8 
9 var message: Text? {
10 // Maksimum 2 cümle
11 Text("Alışveriş listeni arkadaşlarınla paylaş. Birlikte düzenleyebilirsiniz.")
12 }
13 
14 var image: Image? {
15 // SF Symbol — tanıdık, erişilebilir
16 Image(systemName: "square.and.arrow.up")
17 }
18 
19 var options: [any TipOption] {
20 [
21 MaxDisplayCount(2), // 2 kezden fazla gösterme
22 ]
23 }
24}

🏆 Production TipKit — Gerçek Sonuçlar

3 uygulama genelinde 6 ay sonra A/B test sonuçları:

Metrik
Carousel Onboarding
TipKit
Özellik keşif oranı
%22
%61
Onboarding tamamlama
%34
N/A (bağlam bazlı)
Kullanıcı şikayeti
%8
%1.2
Feature adoption (30 gün)
%19
%47

TipKit, feature adoption'ı %148 artırdı. Bağlamsal gösterim, zamanlamadan daha önemli.


🥚 Gizli API: Tips.showAllTipsForTesting()

Simulator'de ve TestFlight'ta tüm tip'leri zorla göstermek için gizli bir yardımcı:

swift
1#if DEBUG
2// Tüm eligibility kurallarını görmezden gel, tüm tip'leri göster
3Tips.showAllTipsForTesting()
4 
5// Veya belirli bir tip'i zorla göster
6let tip = BirSeylerTip()
7tip.invalidate(reason: .actionPerformed) // Önce sıfırla
8// Artık tekrar gösterilecek

TestFlight beta sürecinde QA ekibinin her tip'i test edebilmesi için launchArguments ile de aktifleştirebilirsiniz:

swift
1if CommandLine.arguments.contains("--reset-tips") {
2 try? Tips.resetDatastore()
3}
4if CommandLine.arguments.contains("--show-all-tips") {
5 Tips.showAllTipsForTesting()
6}

🎁 Bonus: SwiftUI Preview'da TipKit

Preview'da tip'leri doğrudan test etmek için:

swift
1#Preview {
2 let _ = Tips.showAllTipsForTesting()
3 return AnaSayfa()
4}
5 
6// Belirli tip durumunu test et
7#Preview("Tip Gösteriliyor") {
8 let _ = try? Tips.configure([.displayFrequency(.immediate)])
9 let _ = Tips.showAllTipsForTesting()
10 return NavigationStack {
11 UrunListesi()
12 }
13}

Sonuç

TipKit, onboarding UX'ini kökten değiştiriyor. "Kullanıcı uygulamamı nasıl öğrenir?" sorusunun cevabı artık carousel veya modal değil: doğru anda, doğru yerde, doğru bağlamda.

Temel öneriler:

  1. Rules engine'i kullan: Zaman bazlı değil, davranış bazlı koşullar
  2. popoverTip > TipView: Spesifik elementleri işaret et
  3. MaxDisplayCount(1-3) ayarla: Kullanıcıyı rahatsız etme
  4. Analytics ekle: tipStatusUpdated'ı dinle, conversion takip et
  5. HIG kurallarına uyu: Kritik akışlarda tip gösterme

Daha fazla iOS geliştirme içeriği için Swift 6 yeniliklerine, iOS 19 beta incelememize ve SwiftUI vs UIKit rehberimize göz atabilirsiniz.

Kaynaklar:

Etiketler

#TipKit#Onboarding#UX#iOS#Feature Discovery#Swift#2026
Muhittin Çamdalı

Muhittin Çamdalı

Senior iOS Developer

12+ yıllık deneyime sahip iOS Developer. Swift, SwiftUI ve modern iOS mimarileri konusunda uzman. Apple platformlarında performanslı ve kullanıcı dostu uygulamalar geliştiriyorum.

iOS Geliştirme Haberleri

Haftalık Swift tips, SwiftUI tricks ve iOS best practices. Spam yok, sadece değerli içerik.

Gizliliğinize saygı duyuyoruz. İstediğiniz zaman abonelikten çıkabilirsiniz.

Paylaş

Bunu da begenebilirsiniz