iOS SDK'da flow ve paywall yüklemeyi optimize etme

iOS’ta güvenilir bir flow veya paywall yüklemesi üç şeyi yapar: hızlı görüntülenir, kitleye özel varyantı döndürür ve ağ yavaş olduğunda sorunsuz yedek görüntüler. Aşağıdaki kurallar bu hedefe ulaşmak için zamanlama, önbellekleme ve yedek desenlerini kapsar.

Tip

Bu kurallar, Adapty.activate() ve Adapty.identify() fonksiyonlarının zaten tamamlanmış olduğunu varsayar. Bkz. iOS SDK’da çağrı sırası.

Kurallar ve tuzaklar

Bunu yapınBunu yapmayınNeden
Göstermek üzere olduğunuz placement’ı çekin ya da preloadFlows ile önbelleği ısıtın (SDK 4.1+).Başlangıçta kendi eşzamanlı getFlow çağrılarınızı zincirlemeyin.Elle yazılmış bir önceden yükleme patlaması ana thread’i bloke eder ve siyah ekrana yol açar. preloadFlows bunun için tasarlanmıştır ve zaman aşımı bütçesini toplu olarak paylaşır.
Attribution’ın çözülmesine fırsat tanıdıktan sonra getFlow’u çekin — örneğin activate’ten 1–2 saniye sonra ya da didLoadLatestProfile tetiklendikten sonra.getFlow’u App.init() içinde çağırmayın.Attribution henüz tamamlanmamıştır. Flow, varsayılan kitleye göre çözümlenir ve segment ile ASA kişiselleştirmesini sessizce atlar.
Her placement için bir loadTimeout belirleyin ve bir yedek paywall yapılandırın.getFlow’u süresiz olarak beklemeyin.Zaman aşımı olmadan, bağlantısı zayıf kullanıcılar ağ çözümlenene kadar boş ekran görür — ya da uygulamayı kapatır.

Herhangi bir fetch işleminde loadTimeout tetiklendiğinde — basit bir getFlow dahil — SDK, önbelleğe alınmış bir varyant varsa onu döner; yoksa kalan süre içinde varsayılan kitle (All Users) varyantını getirir. Hedefleme o istek için kaybolur, ertelenmez: segmentler ve attribution tabanlı kitleler sonuca uygulanmaz.

fetchPolicy ve loadTimeout parametre referansı için Paywall ve ürünleri getirme sayfasına, doğru placement seçimi için ise Placement’lar sayfasına bakın.

Placement’ları önceden yükle

Info

preloadFlows ve preloadFlowsForDefaultAudience, SDK sürüm 4.1’den itibaren kullanılabilir.

preloadFlows, flow JSON’ını önceden önbelleğe alır — her placement için bir istek. Ardından her zamanki gibi kullanabilirsiniz: flow için getFlow, görünüm yapılandırması için getFlowConfiguration.

fetchPolicy, sonraki getFlow’un önce hangi katmanı okuyacağını belirler; önbelleğe erişip erişemeyeceğini değil:

  • .returnCacheDataElseLoad, önbelleğe alınmış kopyayı önce okur ve yalnızca önbellekte hiçbir şey yoksa ağa gider. .returnCacheDataIfNotExpiredElseLoad(maxAge:) ise kopya maxAge’den daha yeni olduğu sürece aynı şekilde davranır.
  • Varsayılan olan .reloadRevalidatingCacheData, önce ağa gider ve istek başarısız olursa ya da zaman aşımına uğrarsa önceden yüklenmiş kopyaya geri döner.

Ön yükleme her iki durumda da işe yarar, ancak farklı biçimlerde: önbellek öncelikli bir politika isteği tamamen ortadan kaldırırken, varsayılan politika isteği korur ve yedek olarak kullanılabilecek sıcak bir kopya kazanır.

Hangi placement’ların oturumda gerekli olduğunu bildiğinizde ancak henüz göstermek istemediğinizde kullanın — örneğin, activate ve identify tamamlandıktan hemen sonra, kullanıcının henüz dokunmadığı bir butonun arkasındaki flow için.

Parametreler:

  • placementIds (gerekli): önceden yüklenecek placement’lar. Boş ve yinelenen ID’ler göz ardı edilir.
  • loadTimeout (isteğe bağlı): tüm toplu işlem için saniye cinsinden zaman aşımı, placement başına değil. Varsayılan değer 5 saniyedir; 1 saniyenin altındaki değerler 1 saniyeye yükseltilir.

Bilmeniz gereken davranışlar:

  • Metot, her placement’i denedikten sonra hata fırlatır ve hata, placement başına başarısızlıkları bir araya getirir. Bir placement’teki başarısızlık diğerlerini durdurmaz.
  • Bir placement zaman aşımına uğrar veya ağ hatasıyla başarısız olursa, SDK o placement için varsayılan kitle varyasyonuna geri döner. Diğer hatalar olduğu gibi raporlanır.
  • Zaman aşımı, kitleye yönelik fetch tamamlanmadan tetiklenirse, SDK kalan süre içinde varsayılan kitle varyasyonunu denemeye devam eder.
  • Ön yükleme yalnızca önbelleği ısıtır. İçerik döndürmez; içeriği göstermek için yine de getFlow çağırmanız gerekir.

Preload’un kapsadıkları

Bir flow ekrana katmanlar halinde gelir. Preload, tıpkı getFlow’un yaptığı gibi yalnızca ilk katmanı kapsar:

KatmanKim tarafından alınırPreload ile ısıtılır mı
Flow JSON — seçilen varyant, ürün ID’leri ve remote configgetFlowEvet
UI düzeni — ekranın yapısı, stili ve metinlerigetFlowConfigurationHayır
Görseller; video öğesinin yerine geçen sabit kare dahilgetFlowConfiguration, arka plandaHayır
Video dosyalarıEkran render edilirken sistem oynatıcısıSDK tarafından önbelleğe alınmaz

getFlowConfiguration layout’u bekler; bu nedenle önceden yükleme yapılmış olsa bile belirli bir layout için yapılan ilk istek bir tur-gidiş-dönüş maliyeti gerektirir. SDK ardından bu layout’u kendi disk önbelleğinde tutar; bu önbellek uygulama yeniden başlatmalarından sonra da hayatta kalır ve herhangi bir ağ çağrısından önce okunur, dolayısıyla maliyet her istekte değil yalnızca ilk istekte oluşur. SDK layout’u edindikten sonra, çağrıdan bağımsız olarak görselleri önbelleğe almaya başlar: ekranı bekletmez ve bittiğinde bunu bildiren bir callback, delegate metodu veya hata yoktur.

Hangi placement’ın başarısız olduğunu öğrenin

Fırlatılan hata, networkFailed (2005) koduyla tüm toplu işlemi kapsayan tek bir AdaptyError’dır. Tek tek başarısızlıkları görmek için preloadErrors özelliğini okuyun — placement ID’sine göre anahtarlanmış bir sözlüktür:

do {
    try await Adapty.preloadFlows(placementIds: ["onboarding", "main_paywall"])
} catch {
    for (placementId, placementError) in error.preloadErrors ?? [:] {
        // log or retry the individual placement
    }
}

preloadErrors değeri, bir preload çağrısından kaynaklanmayan hatalar için nil olur; bu nedenle nil değerini “hata yok” olarak değil, “preload hatası değil” olarak değerlendirin.

Kitle segmentasyonunu atlayın

Kitle segmentasyonunu hiç beklemeden önbelleği ısıtmak için varsayılan kitle varyantını kullanın:

try await Adapty.preloadFlowsForDefaultAudience(placementIds: ["main_paywall"])

Uygulama paketinden ilk ekran medyasını göster

Bir flow, resim ve videolarını Adapty’den indirir. İlk ekranın medyasını anında göstermek için bunları uygulama paketinden sunun. Bu yöntem, mevcut yerel bir onboarding’in görselleri gibi zaten paketlediğiniz medyaları yeniden kullanmanın iyi bir yoludur.

  1. Flow & Paywall Builder’da, resim veya video üzerinde bir özel medya ID’si ayarlayın. Oraya yüklediğiniz dosya yedek olarak kalır.
  2. Dosyayı uygulama paketinize ekleyin.
  3. getFlowConfiguration çağrısı yaparken, söz konusu ID için paketlenmiş dosyayı assetsResolver aracılığıyla iletin:
// "welcome_video" is the custom media ID set in the Flow & Paywall Builder
let bundledAssets: [String: AdaptyCustomAsset] = [
    "welcome_video": .video(
        .file(
            url: Bundle.main.url(forResource: "welcome", withExtension: "mp4")!,
            preview: .uiImage(value: UIImage(named: "welcome_poster")!),
            resolution: CGSize(width: 1080, height: 1920)
        )
    ),
]

let flowConfig = try await AdaptyUI.getFlowConfiguration(
    forFlow: flow,
    assetsResolver: bundledAssets
)

Paketlenmiş dosyalar uygulamanızın indirme boyutunu artırır; bu yüzden yalnızca kullanıcıların ilk gördüğü medyaları paketleyin.

Paketlemediğiniz medyalar yine de hemen görünür: görünüm yapılandırması, video duraklatma karesi dahil her görselin küçük, düşük çözünürlüklü bir kopyasını içerir ve tam dosya yüklenene kadar bunu gösterir.

assetsResolver için tam referansa ulaşmak üzere Varlıkları özelleştirin sayfasına bakın.

Zayıf bağlantı için ayarlama

Sürekli zayıf bağlantının yaşandığı pazarlar için (kırsal alanlar, toplu taşıma, yönlendirme sorunları yaşanan bölgeler):

  • İlk fetch dışındaki her fetch için fetchPolicy: .returnCacheDataElseLoad ayarlayın.
  • Adapty kontrol panelindeki her placement için bir yedek paywall yapılandırın.
  • loadTimeout değerini 3–5 saniye olarak ayarlayın ve zaman aşımı gerçekleştiğinde yedek paywalle geçin.
  • Flow görüntülemeyi getProfile() sonucuna bağlamayın. Yavaş bir profilin arayüzü bloke etmemesi için getFlow’u bağımsız olarak çağırın.