# IOS - Adapty Documentation (Full Content)
This file contains the complete content of all documentation pages for this platform.
Locale: tr
Generated on: 2026-07-24T13:02:34.320Z
Total files: 44
---
# File: sdk-installation-ios
---
---
title: "iOS SDK'yı Yükle ve Yapılandır"
description: "Abonelik tabanlı uygulamalar için iOS'ta Adapty SDK kurulumuna ilişkin adım adım kılavuz."
---
Adapty SDK, mobil uygulamanıza sorunsuz entegrasyon için iki temel modül içerir:
- **Core Adapty**: Bu temel SDK, Adapty'nin uygulamanızda düzgün çalışması için zorunludur.
- **AdaptyUI**: Bu isteğe bağlı modül, çapraz platform paywalllar kolayca oluşturmak için kullanıcı dostu, kodsuz bir araç olan [Adapty Paywall Builder](adapty-paywall-builder)'ı kullanıyorsanız gereklidir.
:::tip
Adapty SDK'nın bir mobil uygulamaya nasıl entegre edildiğine dair gerçek bir örnek görmek ister misiniz? Paywall görüntüleme, satın alma yapma ve diğer temel işlevler dahil olmak üzere tam kurulumu gösteren [örnek uygulamalarımıza](https://github.com/adaptyteam/AdaptySDK-iOS/tree/master/Examples) göz atın.
:::
Ayrıca eksiksiz bir uygulama adım adım anlatımı için şu videolara göz atabilirsiniz:
## Gereksinimler \{#requirements\}
SDK teknik olarak çekirdek modül için iOS 13.0+'ı desteklese de, pratikte iOS 15.0+ zorunludur:
- Tüm StoreKit 2 özellikleri iOS 15.0+ gerektirir
- AdaptyUI modülü yalnızca iOS 15.0+ ile çalışır
:::important
Xcode 26.4 veya sonraki sürümlerle derleme yaparken Adapty SDK 3.15.7+ gereklidir.
:::
:::info
SDK'yı yüklemek, Adapty kurulumunun 5. adımıdır. Uygulamanızda satın almalar çalışmadan önce uygulamanızı mağazalara bağlamanız, ardından Adapty Kontrol Paneli'nde ürünler, bir paywall ve bir placement oluşturmanız gerekir. [Hızlı başlangıç kılavuzu](quickstart) tüm gerekli adımları anlatmaktadır.
:::
## Adapty SDK'yı Yükle \{#install-adapty-sdk\}
[](https://github.com/adaptyteam/AdaptySDK-iOS/releases)
Adapty SDK, Swift Package Manager aracılığıyla yüklenir. Xcode'da **File** -> **Add Package Dependency...** yolunu izleyin. Paket bağımlılığı ekleme adımları Xcode sürümüne göre farklılık gösterebileceğinden, gerekirse Xcode belgelerine başvurun.
1. Depo URL'sini girin:
```
https://github.com/adaptyteam/AdaptySDK-iOS.git
```
2. Sürümü seçin (en son kararlı sürüm önerilir) ve **Add Package** düğmesine tıklayın.
3. **Choose Package Products** penceresinde ihtiyacınız olan modülleri seçin:
- **Adapty** (çekirdek modül)
- **AdaptyUI** (isteğe bağlı - yalnızca Paywall Builder kullanmayı planlıyorsanız)
:::note
Not:
- SDK 3.x'te [Kids Mode](kids-mode) özelliğini etkinleştirmek için **Adapty** yerine **Adapty_KidsMode** seçin. SDK 4.0 ve sonrasında ise normal modülleri seçin — Kids Mode, `KidsMode` paket özelliği aracılığıyla etkinleştirilir.
- Listeden başka herhangi bir paket seçmeyin – bunlara ihtiyacınız olmayacak.
:::
4. Kurulumu tamamlamak için **Add Package** düğmesine tıklayın.
5. **Kurulumu doğrulayın:** Proje gezgininizde **Package Dependencies** altında "Adapty" (ve seçtiyseniz "AdaptyUI") görünmelidir.
:::important
Adapty iOS SDK 4.0 ön sürümdür. Swift Package Manager, **Up to Next Major Version** (`from:`) kuralıyla beta sürümlerini çözemez; bu nedenle tam sürümü sabitlemeniz gerekir. Xcode'da **Dependency Rule** ayarını **Exact Version** olarak belirleyin ve `4.0.0-beta.2` girin. `Package.swift` dosyasında `.exact("4.0.0-beta.2")` kullanın. Bkz. [Adapty iOS SDK'yı v4'e Taşıma](migration-to-ios-sdk-v4).
:::
## Adapty SDK'nın Adapty modülünü etkinleştirin \{#activate-adapty-module-of-adapty-sdk\}
Adapty SDK'yı uygulama kodunuzda etkinleştirin.
:::note
Adapty SDK'nın uygulamanızda yalnızca bir kez etkinleştirilmesi gerekir.
:::
**Public SDK Key**'inizi almak için:
1. Adapty Kontrol Paneli'ne gidin ve [**App settings → General**](https://app.adapty.io/settings/general) sayfasına gidin.
2. **Api keys** bölümünden **Public SDK Key**'i kopyalayın (Secret Key'i değil).
3. Koddaki `"YOUR_PUBLIC_SDK_KEY"` ifadesini değiştirin.
Ya da [Adapty CLI](developer-cli) kullanarak programatik olarak alın:
```
npm install -g adapty
adapty auth login
adapty apps list
```
Ya da doğrudan:
```
npx adapty auth login
adapty apps list
```
- Adapty başlatma işlemi için **Public SDK key** kullandığınızdan emin olun; **Secret key** yalnızca [sunucu taraflı API](getting-started-with-server-side-api) için kullanılmalıdır.
- **SDK key**'leri her uygulama için benzersizdir, bu nedenle birden fazla uygulamanız varsa doğru olanı seçtiğinizden emin olun.
```swift showLineNumbers
@main
struct YourApp: App {
init() {
// Configure Adapty SDK
let configurationBuilder = AdaptyConfiguration
.builder(withAPIKey: "YOUR_PUBLIC_SDK_KEY") // Get from Adapty dashboard
Adapty.logLevel = .verbose // recommended for development and the first production release
let config = configurationBuilder.build()
// Activate Adapty SDK asynchronously
Task {
do {
try await Adapty.activate(with: config)
} catch {
// Handle error appropriately for your app
print("Adapty activation failed: ", error)
}
}
var body: some Scene {
WindowGroup {
// Your content view
}
}
}
}
```
```swift showLineNumbers
// In your AppDelegate class:
// If you only use an AppDelegate, place the following code in the
// application(_:didFinishLaunchingWithOptions:) method.
// If you use a SceneDelegate, place the following code in the
// scene(_:willConnectTo:options:) method.
Task {
do {
let configurationBuilder = AdaptyConfiguration
.builder(withAPIKey: "YOUR_PUBLIC_SDK_KEY") // Get from Adapty dashboard
.with(logLevel: .verbose) // recommended for development and the first production release
let config = configurationBuilder.build()
try await Adapty.activate(with: config)
} catch {
// Handle error appropriately for your app
print("Adapty activation failed: ", error)
}
}
```
:::important
Diğer Adapty SDK metotlarını çağırmadan önce `activate` işleminin tamamlanmasını bekleyin. Tam sıralama için [iOS SDK'da çağrı sırası](ios-sdk-call-order) sayfasına bakın.
:::
Şimdi uygulamanızda paywallları ayarlayın:
- [Adapty Paywall Builder](adapty-paywall-builder) kullanıyorsanız, önce aşağıdaki [AdaptyUI modülünü etkinleştirin](#activate-adaptyui-module-of-adapty-sdk), ardından [Paywall Builder hızlı başlangıç kılavuzunu](ios-quickstart-paywalls) takip edin.
- Kendi paywall arayüzünüzü oluşturuyorsanız [özel paywalllar için hızlı başlangıç kılavuzuna](ios-quickstart-manual) bakın.
## Adapty SDK'nın AdaptyUI Modülünü Etkinleştirin \{#activate-adaptyui-module-of-adapty-sdk\}
[Paywall Builder](adapty-paywall-builder) kullanmayı planlıyorsanız ve [AdaptyUI modülünü kurduysanız](sdk-installation-ios#install-adapty-sdk), AdaptyUI'ı da etkinleştirmeniz gerekir.
:::important
Kodunuzda, AdaptyUI'ı etkinleştirmeden önce Adapty çekirdek modülünü etkinleştirmeniz gerekir.
:::
```swift showLineNumbers title="Swift"
@main
struct YourApp: App {
init() {
// ...ConfigurationBuilder steps
// Activate Adapty SDK asynchronously
Task {
do {
try await Adapty.activate(with: config)
try await AdaptyUI.activate()
} catch {
// Handle error appropriately for your app
print("Adapty activation failed: ", error)
}
}
// main body...
}
}
```
```swift showLineNumbers title="UIKit"
// If you only use an AppDelegate, place the following code in the
// application(_:didFinishLaunchingWithOptions:) method.
// If you use a SceneDelegate, place the following code in the
// scene(_:willConnectTo:options:) method.
Task {
do {
let configurationBuilder = AdaptyConfiguration
.builder(withAPIKey: "YOUR_PUBLIC_SDK_KEY") // Get from Adapty dashboard
.with(logLevel: .verbose) // recommended for development
let config = configurationBuilder.build()
try await Adapty.activate(with: config)
try await AdaptyUI.activate()
} catch {
// Handle error appropriately for your app
print("Adapty activation failed: ", error)
}
}
```
:::tip
İsteğe bağlı olarak, AdaptyUI'ı etkinleştirirken [paywall'lar için varsayılan önbellekleme ayarlarını geçersiz kılabilirsiniz](#set-up-media-cache-configuration-for-adaptyui).
:::
## İsteğe Bağlı Kurulum \{#optional-setup\}
### Günlük Kaydı \{#logging\}
#### Günlük kayıt sistemini kurma \{#set-up-the-logging-system\}
Adapty, neler olduğunu anlamanıza yardımcı olmak için hataları ve diğer önemli bilgileri kaydeder. Aşağıdaki günlük seviyeleri mevcuttur:
| Level | Description |
| ---------- | ------------------------------------------------------------ |
| `error` | Yalnızca hatalar loglanır |
| `warn` | Hatalar ve SDK'dan gelen, kritik hatalara yol açmayan ancak dikkat edilmesi gereken mesajlar loglanır |
| `info` | Hatalar, uyarılar ve çeşitli bilgi mesajları loglanır |
| `verbose` | Hata ayıklama sırasında yararlı olabilecek her türlü ek bilgi (fonksiyon çağrıları, API sorguları vb.) loglanır |
```swift showLineNumbers
let configurationBuilder = AdaptyConfiguration
.builder(withAPIKey: "YOUR_PUBLIC_SDK_KEY")
.with(logLevel: .verbose) // recommended for development
```
#### Günlük sistemi mesajlarını yönlendirin \{#redirect-the-logging-system-messages\}
Adapty'nin günlük mesajlarını kendi sisteminize göndermek veya bir dosyaya kaydetmek istiyorsanız `setLogHandler` metodunu kullanın ve özel günlük mantığınızı bu metodun içinde uygulayın. Bu işleyici, mesaj içeriği ve önem derecesini içeren günlük kayıtları alır.
```swift showLineNumbers title="Swift"
Adapty.setLogHandler { record in
writeToLocalFile("Adapty \(record.level): \(record.message)")
}
```
### Veri politikaları \{#data-policies\}
Adapty, siz açıkça göndermediğiniz sürece kullanıcılarınızın kişisel verilerini saklamaz. Ancak mağaza veya ülke yönergelerine uymak için ek veri güvenliği politikaları uygulayabilirsiniz.
#### IDFA toplama ve paylaşımını devre dışı bırakma \{#disable-idfa-collection-and-sharing\}
Adapty modülünü etkinleştirirken IDFA toplama ve paylaşımını devre dışı bırakmak için `idfaCollectionDisabled` değerini `true` olarak ayarlayın.
App Store İnceleme Kuralları'na uymak veya IDFA uygulamanız için gerekli olmadığında App Tracking Transparency istemini tetiklemekten kaçınmak için bu parametreyi kullanın. Varsayılan değer `false` şeklindedir. IDFA toplama hakkında daha fazla bilgi için [Analytics entegrasyonu](analytics-integration#disable-collection-of-advertising-identifiers) bölümüne bakın.
```swift showLineNumbers
let configurationBuilder =
AdaptyConfiguration
.builder(withAPIKey: "YOUR_PUBLIC_SDK_KEY")
.with(idfaCollectionDisabled: true)
```
#### IP toplama ve paylaşımını devre dışı bırakma \{#disable-ip-collection-and-sharing\}
Adapty modülünü etkinleştirirken, kullanıcı IP adresi toplama ve paylaşımını devre dışı bırakmak için `ipAddressCollectionDisabled` parametresini `true` olarak ayarlayın. Varsayılan değer `false`'tur.
Bu parametreyi; kullanıcı gizliliğini artırmak, bölgesel veri koruma yönetmeliklerine (GDPR veya CCPA gibi) uymak ya da uygulamanızda IP tabanlı özelliklere ihtiyaç duyulmadığında gereksiz veri toplamayı azaltmak için kullanabilirsiniz.
```swift showLineNumbers
let configurationBuilder =
AdaptyConfiguration
.builder(withAPIKey: "YOUR_PUBLIC_SDK_KEY")
.with(ipAddressCollectionDisabled: true)
```
#### AdaptyUI'da paywall'lar için medya önbellek yapılandırması \{#media-cache-configuration-for-paywalls-in-adaptyui\}
AdaptyUI yapılandırmasının isteğe bağlı olduğunu unutmayın. AdaptyUI modülünü yapılandırma olmadan da etkinleştirebilirsiniz. Ancak yapılandırmayı kullanıyorsanız tüm parametreler zorunludur.
```swift showLineNumbers title="Swift"
// Configure AdaptyUI
let adaptyUIConfiguration = AdaptyUI.Configuration(
mediaCacheConfiguration: .init(
memoryStorageTotalCostLimit: 100 * 1024 * 1024,
memoryStorageCountLimit: .max,
diskStorageSizeLimit: 100 * 1024 * 1024
)
)
// Activate AdaptyUI
AdaptyUI.activate(configuration: adaptyUIConfiguration)
```
Parametreler:
| Parametre | Zorunluluk | Açıklama |
| :-------------------------- | :--------- | :----------------------------------------------------------- |
| memoryStorageTotalCostLimit | zorunlu | Depolama alanının bayt cinsinden toplam maliyet sınırı. |
| memoryStorageCountLimit | zorunlu | Bellek depolama alanının öğe sayısı sınırı. |
| diskStorageSizeLimit | zorunlu | Depolama alanının diskteki dosya boyutu sınırı (bayt cinsinden). 0, sınır olmadığı anlamına gelir. |
### İşlem Tamamlama Davranışı \{#transaction-finishing-behavior\}
:::info
Bu özellik SDK 3.12.0 sürümünden itibaren kullanılabilir.
:::
Adapty, varsayılan olarak işlemleri başarılı doğrulamanın ardından otomatik olarak tamamlar. Ancak gelişmiş işlem doğrulamasına ihtiyaç duyuyorsanız (sunucu taraflı makbuz doğrulama, sahtekarlık tespiti veya özel iş mantığı gibi), SDK'yı manuel işlem tamamlama modunda çalışacak şekilde yapılandırabilirsiniz.
```swift showLineNumbers title="Swift"
let configurationBuilder = AdaptyConfiguration
.builder(withAPIKey: "YOUR_PUBLIC_SDK_KEY")
.with(transactionsFinishBehavior: .manual) // .auto varsayılandır
```
İşlemlerin nasıl tamamlanacağına dair daha fazla ayrıntı için [kılavuza](ios-transaction-management) bakın.
### Yedekten geri yüklemede verileri temizle \{#clear-data-on-backup-restore\}
`clearDataOnBackup` değeri `true` olarak ayarlandığında, SDK uygulamanın bir iCloud yedeğinden geri yüklendiğini algılar ve önbelleğe alınmış profil bilgileri, ürün ayrıntıları ve paywaller dahil yerel olarak depolanan tüm SDK verilerini siler. SDK ardından temiz bir durumla başlatılır. Varsayılan değer `false`'tur.
:::note
Yalnızca yerel SDK önbelleği silinir. Apple ile olan işlem geçmişi ve Adapty sunucularındaki kullanıcı verileri değişmeden kalır.
:::
```swift showLineNumbers
let configurationBuilder = AdaptyConfiguration
.builder(withAPIKey: "YOUR_PUBLIC_SDK_KEY")
.with(clearDataOnBackup: true) // default – false
```
## Sorun Giderme \{#troubleshooting\}
#### Tuist ile Swift 6 eşzamanlılık hatası \{#swift-6-concurrency-error-with-tuist\}
[Tuist](https://tuist.dev/) ile derleme yaparken Swift 6 strict concurrency derleme hatalarıyla karşılaşabilirsiniz. Tipik belirtiler arasında `AdaptyUIBuilderLogic` içinde `@Sendable` özellik uyumsuzlukları veya benzer modüller arası Sendability hataları yer alır.
Bu durum, Tuist'in SPM paketlerinden Xcode projeleri oluşturmasına ancak `swift-tools-version: 6.0` ayarını korumamasına bağlıdır. Sonuç olarak bazı Adapty hedefleri (`Adapty`, `AdaptyUI`, `AdaptyUIBuilder`) Swift 5 kurallarıyla derlenirken diğerleri Swift 6 kullanır ve bu durum modüller arası `@Sendable` uyuşmazlıklarına yol açar.
**Düzeltme**: Adapty SDK **3.15.5** veya sonraki bir sürüme yükseltin; bu sürüm, karışık Swift dil sürümlerinden bağımsız olarak sorunu çözer.
**Geçici çözüm**: Yükseltme yapamıyorsanız Tuist yapılandırmanızda üç Adapty hedefinin tamamı için Swift 6'yı açıkça belirtin:
```swift showLineNumbers
targetSettings: [
"Adapty": .init().swiftVersion("6"),
"AdaptyUI": .init().swiftVersion("6"),
"AdaptyUIBuilder": .init().swiftVersion("6"),
]
```
---
# File: ios-quickstart-paywalls
---
---
title: "iOS SDK'da Flow Builder ile satın almaları etkinleştirin"
description: "Adapty Flow Builder ile uygulama içi satın almaları etkinleştirmeye yönelik hızlı başlangıç kılavuzu."
---
Uygulama içi satın almaları etkinleştirmek için üç temel kavramı anlamanız gerekir:
- [**Ürünler**](product) – kullanıcıların satın alabileceği her şey (abonelikler, consumable'lar, süresiz erişim)
- [**Flow'lar**](adapty-flow-builder) – ürünleri kullanıcılara sunan, no-code Flow Builder ile oluşturulan ekran dizileri. SDK bunları `getFlow` ile alır. Kullanıcı arayüzünü kendi kodunuzla oluşturmayı tercih ederseniz, bunun yerine paywall kullanın — bkz. [Paywallları manuel olarak uygulama](ios-quickstart-manual).
- [**Placement'lar**](placements) – uygulamanızda flow'ları nerede ve ne zaman göstereceğiniz (`main`, `onboarding`, `settings` gibi). Flow'ları kontrol panelinde placement'lara bağlar, ardından kodunuzda placement ID'si ile talep edersiniz. Bu sayede A/B testleri çalıştırmak ve farklı kullanıcılara farklı flow'lar göstermek çok kolay olur.
Adapty, uygulamanızda satın alımları etkinleştirmeniz için üç yol sunar. Uygulama gereksinimlerinize göre birini seçin:
| Uygulama | Karmaşıklık | Ne zaman kullanılır |
|---|---|---|
| Adapty Flow Builder | ✅ Kolay | [No-code builder'da eksiksiz, satın almaya hazır bir flow oluşturursunuz](quickstart-paywalls). Adapty bunu otomatik olarak render eder ve tüm karmaşık satın alma akışını, makbuz doğrulamasını ve abonelik yönetimini arka planda halleder. |
| Elle oluşturulan paywalllar | 🟡 Orta | Paywall arayüzünüzü uygulama kodunuzda kendiniz uygularsınız; ancak ürün tekliflerinde esnekliği korumak için flow nesnesini yine Adapty'den alırsınız. [Rehbere](ios-quickstart-manual) göz atın. |
| Observer modu | 🔴 Zor | Kendi satın alma altyapınız zaten mevcuttur ve bunu kullanmaya devam etmek istersiniz. Observer modunun Adapty'de bazı kısıtlamaları olduğunu unutmayın. [Makaleye](observer-vs-full-mode) bakın. |
:::important
**Aşağıdaki adımlar, Adapty Flow Builder'da oluşturulan bir flow'un nasıl uygulanacağını göstermektedir.**
Paywall arayüzünü kendiniz oluşturmayı tercih ediyorsanız, bkz. [Paywall'ları manuel olarak uygulama](ios-quickstart-manual).
:::
Adapty Flow Builder'da oluşturulan bir flow'u görüntülemek için uygulama kodunuzda yalnızca şunları yapmanız gerekir:
1. **Flow'u alın**: Adapty'den alın.
2. **Görüntüleyin, satın almaları Adapty sizin için yönetecektir**: Görünümü uygulamanızda gösterin.
3. **Buton eylemlerini yönetin**: Kullanıcı etkileşimlerini uygulamanızın bu etkileşimlere verdiği yanıtlarla ilişkilendirin. Örneğin, kullanıcılar butona tıkladığında bağlantılar açın veya flow'u kapatın.
## Başlamadan önce \{#before-you-start\}
Başlamadan önce şu adımları tamamlayın:
1. Adapty Kontrol Paneli'nde [uygulamanızı App Store'a bağlayın](initial_ios).
2. Adapty'de [ürünlerinizi oluşturun](create-product).
3. [Bir flow oluşturun ve ürünleri ekleyin](create-paywall).
4. [Bir placement oluşturun ve flow'u ekleyin](create-placement).
5. Uygulama kodunuzda [Adapty SDK'yı yükleyip etkinleştirin](sdk-installation-ios). Bu kılavuz Adapty iOS SDK v4 API'lerini kullanmaktadır.
## 1. Flow'u edinin \{#1-get-the-flow\}
Flow'larınız, kontrol panelinde yapılandırılmış placement'larla ilişkilendirilir. Placement'lar, farklı kitleler için farklı flow'lar çalıştırmanıza veya [A/B testi](ab-tests) yapmanıza olanak tanır.
Adapty Flow Builder'da oluşturulan bir flow'u edinmek için şunları yapmanız gerekir:
1. `getFlow` metodunu kullanarak [placement](placements) ID'sine göre `flow` nesnesini alın ve bir görünüm yapılandırması içerip içermediğini kontrol edin.
2. `getFlowConfiguration` metodunu kullanarak görünüm yapılandırmasını edinin. Bu yapılandırma, flow'u görüntülemek için gereken UI öğelerini ve stil bilgilerini içerir.
```swift
func loadFlow() async {
let flow = try await Adapty.getFlow(placementId: "YOUR_PLACEMENT_ID")
guard flow.hasViewConfiguration else {
print("Flow'un bir görünüm yapılandırması yok")
return
}
flowConfiguration = try await AdaptyUI.getFlowConfiguration(forFlow: flow)
}
```
## 2. Flow'u göster \{#display-the-flow\}
Artık flow konfigürasyonuna sahipsiniz; flow'u göstermek için birkaç satır kod eklemeniz yeterli.
SwiftUI'da flow'u gösterirken aynı zamanda olayları da ele almanız gerekir. `didFinishPurchase`, `didFailPurchase`, `didFinishRestore`, `didFailRestore` ve `didReceiveError` zorunludur. Test sırasında bu olayları kaydetmek için aşağıdaki kod parçacığını doğrudan kopyalayabilirsiniz.
:::tip
Flow, başarılı bir satın alma işleminin ardından otomatik olarak kapanmaz. `didFinishPurchase` içinde, flow'u kapatmak için sunum bağlantınızı `false` olarak ayarlayın ya da flow'un sonraki ekranlarına devam etmesi için hiçbir şey yapmayın.
:::
```swift
.flow(
isPresented: $flowPresented,
flowConfiguration: flowConfiguration,
didFinishPurchase: { product, purchaseResult in
print("Purchase finished successfully")
flowPresented = false // or do nothing to let the flow continue
},
didFailPurchase: { product, error in
print("Purchase failed: \(error)")
},
didFinishRestore: { profile in
print("Restore finished successfully")
},
didFailRestore: { error in
print("Restore failed: \(error)")
},
didReceiveError: { error in
flowPresented = false
print("Flow error: \(error)")
}
)
```
```swift
func presentFlow(with config: AdaptyUI.FlowConfiguration) {
let flowController = try AdaptyUI.flowController(
with: config,
delegate: self
)
present(flowController, animated: true)
}
```
`AdaptyFlowControllerDelegate`'i olayları ele almak için uygulayın. En azından varsayılan uygulaması olmayan dört metodu implemente edin. Dikkat: controller başarılı bir satın almanın ardından kendini kapatmaz — `didFinishPurchase` içinde kapatın ya da flow'un sonraki ekranlarına devam etmesine izin vermek için hiçbir şey yapmayın:
```swift
extension YourViewController: AdaptyFlowControllerDelegate {
func flowController(_ controller: AdaptyFlowController,
didFinishPurchase product: AdaptyPaywallProduct,
purchaseResult: AdaptyPurchaseResult) {
if !purchaseResult.isPurchaseCancelled {
controller.dismiss(animated: true) // or do nothing to let the flow continue
}
}
func flowController(_ controller: AdaptyFlowController,
didFailPurchase product: AdaptyPaywallProduct,
error: AdaptyError) {
print("Purchase failed: \(error)")
}
func flowController(_ controller: AdaptyFlowController,
didFinishRestoreWith profile: AdaptyProfile) {
print("Restore finished successfully")
}
func flowController(_ controller: AdaptyFlowController,
didFailRestoreWith error: AdaptyError) {
print("Restore failed: \(error)")
}
}
```
:::info
Bir flow'un nasıl görüntüleneceğine dair daha fazla ayrıntı için [rehberimize](ios-present-paywalls) bakın.
:::
## 3. Buton eylemlerini yönetin \{#handle-button-actions\}
Kullanıcılar butona tıkladığında, iOS SDK satın alma işlemlerini, geri yüklemeleri, flow'u kapatmayı ve bağlantı açmayı otomatik olarak yönetir.
Ancak bazı butonların özel veya önceden tanımlanmış kimlikleri vardır ve kodunuzda eylemlerin yönetilmesini gerektirir. Ya da varsayılan davranışlarını geçersiz kılmak isteyebilirsiniz.
Örneğin, kapat butonunu şu şekilde yönetebilirsiniz. UIKit'te, `.close` tetiklendiğinde SDK controller'ı otomatik olarak kapatır — yalnızca özel bir davranış istiyorsanız geçersiz kılın. SwiftUI'da ise `isPresented` binding'inizi kendiniz `false` olarak ayarlamanız gerekir.
:::tip
Buton [aksiyonlarını](handle-paywall-actions) ve [olayları](ios-handling-events) nasıl yöneteceğinize dair kılavuzlarımızı okuyun.
:::
```swift
.flow(
isPresented: $flowPresented,
flowConfiguration: flowConfiguration,
didPerformAction: { action in
switch action {
case .close:
flowPresented = false // dismiss the flow when the user taps close
default:
break
}
},
didFinishPurchase: { product, purchaseResult in flowPresented = false },
didFailPurchase: { product, error in /* handle the error */ },
didFinishRestore: { profile in /* check access level and dismiss */ },
didFailRestore: { error in /* handle the error */ },
didReceiveError: { error in flowPresented = false }
)
```
```swift
extension YourViewController: AdaptyFlowControllerDelegate {
func flowController(_ controller: AdaptyFlowController,
didPerform action: AdaptyUI.Action) {
switch action {
case .close:
controller.dismiss(animated: true) // varsayılan davranış — yalnızca gerektiğinde geçersiz kılın
default:
break
}
}
}
```
## Sonraki adımlar \{#next-steps\}
:::tip
Sorularınız mı var ya da sorunlarla mı karşılaşıyorsunuz? Sık sorulan soruların yanıtlarını bulabileceğiniz veya kendi sorularınızı sorabileceğiniz [destek forumumuza](https://adapty.featurebase.app/) göz atın. Ekibimiz ve topluluğumuz yardımcı olmak için burada!
:::
Flow'unuz uygulamada görüntülenmeye hazır. Bir test satın alma işlemini tamamlayabildiğinizden emin olmak için [satın almalarınızı sandbox modunda test edin](test-purchases-in-sandbox).
Şimdi, flow'u veya ücretli özelliklere erişimi doğru kullanıcılara sunduğunuzdan emin olmak için [kullanıcıların access level'ını kontrol etmeniz](ios-check-subscription-status) gerekiyor.
## Tam örnek \{#full-example\}
Bu rehberdeki tüm adımların uygulamanıza birlikte nasıl entegre edileceği aşağıda gösterilmektedir.
```swift
struct ContentView: View {
@State private var flowPresented = false
@State private var flowConfiguration: AdaptyUI.FlowConfiguration?
@State private var isLoading = false
@State private var hasInitialized = false
var body: some View {
VStack {
if isLoading {
ProgressView("Loading...")
} else {
Text("Your App Content")
}
}
.task {
guard !hasInitialized else { return }
await initializeFlow()
hasInitialized = true
}
.flow(
isPresented: $flowPresented,
flowConfiguration: flowConfiguration,
didPerformAction: { action in
switch action {
case .close:
flowPresented = false
default:
break
}
},
didFinishPurchase: { product, purchaseResult in
print("Purchase finished successfully")
flowPresented = false // or do nothing to let the flow continue
},
didFailPurchase: { product, error in
print("Purchase failed: \(error)")
},
didFinishRestore: { profile in
print("Restore finished successfully")
},
didFailRestore: { error in
print("Restore failed: \(error)")
},
didReceiveError: { error in
print("Flow error: \(error)")
flowPresented = false
}
)
}
private func initializeFlow() async {
isLoading = true
defer { isLoading = false }
await loadFlow()
flowPresented = true
}
private func loadFlow() async {
do {
let flow = try await Adapty.getFlow(placementId: "YOUR_PLACEMENT_ID")
guard flow.hasViewConfiguration else {
print("Flow doesn't have a view configuration")
return
}
flowConfiguration = try await AdaptyUI.getFlowConfiguration(forFlow: flow)
} catch {
print("Failed to load: \(error)")
}
}
}
```
```swift
class ViewController: UIViewController {
private var flowConfiguration: AdaptyUI.FlowConfiguration?
override func viewDidLoad() {
super.viewDidLoad()
Task {
await initializeFlow()
}
}
private func initializeFlow() async {
do {
flowConfiguration = try await loadFlow()
if let flowConfiguration {
await MainActor.run {
presentFlow(with: flowConfiguration)
}
}
} catch {
print("Error initializing: \(error)")
}
}
private func loadFlow() async throws -> AdaptyUI.FlowConfiguration? {
let flow = try await Adapty.getFlow(placementId: "YOUR_PLACEMENT_ID")
guard flow.hasViewConfiguration else {
print("Flow doesn't have a view configuration")
return nil
}
return try await AdaptyUI.getFlowConfiguration(forFlow: flow)
}
private func presentFlow(with config: AdaptyUI.FlowConfiguration) {
guard let flowController = try? AdaptyUI.flowController(
with: config,
delegate: self
) else { return }
present(flowController, animated: true)
}
}
extension ViewController: AdaptyFlowControllerDelegate {
func flowController(_ controller: AdaptyFlowController,
didFinishPurchase product: AdaptyPaywallProduct,
purchaseResult: AdaptyPurchaseResult) {
if !purchaseResult.isPurchaseCancelled {
controller.dismiss(animated: true) // or do nothing to let the flow continue
}
}
func flowController(_ controller: AdaptyFlowController,
didFailPurchase product: AdaptyPaywallProduct,
error: AdaptyError) {
print("Purchase failed for \(product.vendorProductId): \(error)")
guard error.adaptyErrorCode != .paymentCancelled else { return }
let message = switch error.adaptyErrorCode {
case .paymentNotAllowed:
"Purchases are not allowed on this device."
default:
"Purchase failed. Please try again."
}
let alert = UIAlertController(title: "Purchase Error", message: message, preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "OK", style: .default))
present(alert, animated: true)
}
func flowController(_ controller: AdaptyFlowController,
didFinishRestoreWith profile: AdaptyProfile) {
print("Restore finished successfully")
controller.dismiss(animated: true)
}
func flowController(_ controller: AdaptyFlowController,
didFailRestoreWith error: AdaptyError) {
print("Restore failed: \(error)")
}
func flowController(_ controller: AdaptyFlowController,
didReceiveError error: AdaptyUIError) {
print("Flow error: \(error)")
controller.dismiss(animated: true)
}
}
```
---
# File: ios-check-subscription-status
---
---
title: "iOS SDK'da abonelik durumunu kontrol etme"
description: "Adapty ile iOS uygulamanızda abonelik durumunu nasıl kontrol edeceğinizi öğrenin."
---
Kullanıcıların ücretli içeriğe erişip erişemeyeceğine ya da bir paywall görüp görmeyeceğine karar vermek için profildeki [access level](access-level) değerini kontrol etmeniz gerekir.
Bu makale, kullanıcılara paywall gösterip göstermeyeceğinizi veya ücretli özelliklere erişim verip vermeyeceğinizi belirlemek amacıyla profil durumuna nasıl erişeceğinizi gösteriyor.
## Abonelik durumunu alma \{#get-subscription-status\}
Kullanıcıya paywall mı yoksa ücretli içerik mi göstereceğinize karar verirken, profillerindeki [access level](access-level) değerini kontrol edersiniz. İki seçeneğiniz var:
- Anlık olarak en güncel profil verisine ihtiyaç duyduğunuzda (örneğin uygulama açılışında) ya da zorla güncelleme yapmak istediğinizde `getProfile` çağırın.
- Abonelik durumu her değiştiğinde otomatik olarak yenilenen yerel bir kopya tutmak için **otomatik profil güncellemelerini** etkinleştirin.
:::important
Adapty'de varsayılan olarak `premium` access level zaten mevcuttur. Birden fazla access level ayarlamanıza gerek yoksa `premium` değerini doğrudan kullanabilirsiniz.
:::
### Profil alma \{#get-profile\}
Abonelik durumunu almanın en kolay yolu, profile erişmek için `getProfile` metodunu kullanmaktır:
```swift showLineNumbers
do {
let profile = try await Adapty.getProfile()
if profile.accessLevels["YOUR_ACCESS_LEVEL"]?.isActive ?? false {
// grant access to premium features
}
} catch {
// handle the error
}
```
```swift showLineNumbers
Adapty.getProfile { result in
if let profile = try? result.get() {
// check the access
profile.accessLevels["YOUR_ACCESS_LEVEL"]?.isActive ?? false {
// grant access to premium features
}
}
}
```
### Abonelik güncellemelerini dinleme \{#listen-to-subscription-updates\}
Uygulamanızda profil güncellemelerini otomatik olarak almak istiyorsanız:
1. İstediğiniz bir türde `AdaptyDelegate` protokolünü uygulayın ve `didLoadLatestProfile` metodunu implemente edin; Adapty, kullanıcının abonelik durumu her değiştiğinde bu metodu otomatik olarak çağırır. Aşağıdaki örnekte abonelik iş akışlarını ve kullanıcı profilini yönetmek için bir `SubscriptionManager` türü kullanıyoruz. Bu tür bir bağımlılık olarak enjekte edilebilir, UIKit uygulamasında singleton olarak kurulabilir ya da uygulamanın ana struct'ından SwiftUI ortamına eklenebilir.
2. Bu metot çağrıldığında güncellenen profil verisini saklayın; böylece ek ağ isteği yapmadan uygulama genelinde kullanabilirsiniz.
```swift
class SubscriptionManager: AdaptyDelegate {
nonisolated func didLoadLatestProfile(_ profile: AdaptyProfile) {
let hasAccess = profile.accessLevels["YOUR_ACCESS_LEVEL"]?.isActive ?? false
// Update UI, unlock content, etc.
}
}
// Set delegate after Adapty activation
Adapty.delegate = subscriptionManager
```
:::note
Adapty, uygulamanız başladığında `didLoadLatestProfile` metodunu otomatik olarak çağırır ve cihaz çevrimdışı olsa bile önbelleğe alınmış abonelik verisini sağlar.
:::
## Profili paywall mantığıyla bağlama \{#connect-profile-with-paywall-logic\}
Paywall gösterme veya ücretli özelliklere erişim verme konusunda anlık kararlar almanız gerektiğinde, kullanıcının profilini doğrudan kontrol edebilirsiniz. Bu yaklaşım; uygulama açılışı, premium bölümlere girerken veya belirli içerikleri görüntülemeden önce gibi senaryolarda kullanışlıdır.
```swift
private func checkAccessLevel() async -> Bool {
do {
let profile = try await Adapty.getProfile()
return profile.accessLevels["YOUR_ACCESS_LEVEL"]?.isActive ?? false
} catch {
print("Error checking access level: \(error)")
return false
}
}
// In your initialization logic:
let hasAccess = await checkAccessLevel()
if !hasAccess {
paywallPresented = true // Show paywall if no access
}
```
```swift
private func checkAccessLevel() async throws -> Bool {
let profile = try await Adapty.getProfile()
return profile.accessLevels["YOUR_ACCESS_LEVEL"]?.isActive ?? false
}
// In your initialization logic:
let hasAccess = try await checkAccessLevel()
if !hasAccess {
presentPaywall(with: paywallConfiguration)
}
```
## Sonraki adımlar \{#next-steps\}
Abonelik durumunu nasıl takip edeceğinizi öğrendiğinize göre, mevcut kimlik doğrulama sisteminizle ve ücretli erişim paylaşım izinleriyle uyumlu olduğundan emin olmak için [kullanıcı profilleriyle nasıl çalışacağınızı](ios-quickstart-identify) öğrenin.
Kendi kimlik doğrulama sisteminiz yoksa bu hiç sorun değil; Adapty kullanıcıları sizin yerinize yönetir. Yine de Adapty'nin anonim kullanıcılarla nasıl çalıştığını öğrenmek için [kılavuzu](ios-quickstart-identify) okuyabilirsiniz.
---
# File: ios-quickstart-identify
---
---
title: "iOS SDK'da kullanıcıları tanımlama"
description: "Uygulama içi abonelik yönetimi için Adapty kurulum hızlı başlangıç kılavuzu."
---
:::important
Bu kılavuz, kendi kimlik doğrulama sisteminiz varsa size yöneliktir. Burada, Adapty'deki kullanıcı profillerinin mevcut kimlik doğrulama sisteminizle uyumlu çalışmasını nasıl sağlayacağınızı öğreneceksiniz.
:::
Kullanıcıların satın alımlarını nasıl yöneteceğiniz, uygulamanızın kimlik doğrulama modeline bağlıdır:
- Uygulamanız arka uç kimlik doğrulaması kullanmıyor ve kullanıcı verilerini depolamıyorsa, [anonim kullanıcılar bölümüne](#anonymous-users) bakın.
- Uygulamanız arka uç kimlik doğrulamasına sahipse (veya ileride sahip olacaksa), [tanımlanmış kullanıcılar bölümüne](#identified-users) bakın.
**Temel kavramlar**:
- **Profiller**, SDK'nın çalışması için gereken varlıklardır. Adapty bunları otomatik olarak oluşturur.
- Anonim **(customer user ID olmadan)** veya tanımlanmış **(customer user ID ile)** olabilirler.
- Adapty'deki profilleri kendi dahili kimlik doğrulama sisteminizle çapraz referanslamak için **customer user ID** sağlarsınız.
Anonim ve tanımlanmış kullanıcılar arasındaki farklar:
| | Anonim kullanıcılar | Tanımlanmış kullanıcılar |
|----------------------------|-------------------------------------------------------------|---------------------------------------------------------------------------------|
| **Satın alma yönetimi** | Mağaza düzeyinde satın alma geri yükleme | Customer user ID aracılığıyla cihazlar arası satın alma geçmişini koruma |
| **Profil yönetimi** | Her yeniden yüklemede yeni profiller | Oturumlar ve cihazlar genelinde aynı profil |
| **Veri sürekliliği** | Anonim kullanıcıların verileri uygulama yüklemesine bağlıdır | Tanımlanmış kullanıcıların verileri uygulama yüklemeleri arasında korunur |
## Anonim kullanıcılar \{#anonymous-users\}
Arka uç kimlik doğrulamanız yoksa, **uygulama kodunda kimlik doğrulamayı işlemenize gerek yoktur**:
1. SDK, uygulamanın ilk açılışında etkinleştirildiğinde, Adapty **kullanıcı için yeni bir profil oluşturur**.
2. Kullanıcı uygulamada bir şey satın aldığında, bu satın alma **Adapty profili ve mağaza hesabıyla ilişkilendirilir**.
3. Kullanıcı uygulamayı **yeniden yüklediğinde** veya **yeni bir cihaza** yüklediğinde, Adapty **aktivasyonda yeni bir anonim profil oluşturur**.
4. Kullanıcı uygulamanızda daha önce satın alma yapmışsa, varsayılan olarak satın alımları SDK aktivasyonunda App Store'dan otomatik olarak senkronize edilir.
:::note
Yedekten geri yükleme, yeniden yüklemeden farklı davranır. Varsayılan olarak, bir kullanıcı yedekten geri yükleme yaptığında SDK önbelleğe alınan verileri korur ve yeni bir profil oluşturmaz. Bu davranışı `clearDataOnBackup` ayarını kullanarak yapılandırabilirsiniz. [Daha fazla bilgi edinin](sdk-installation-ios#clear-data-on-backup-restore).
:::
Anonim kullanıcılarda her yüklemede yeni profiller oluşturulacaktır, ancak bu bir sorun değildir; çünkü Adapty analitiğinde [yeni yükleme olarak neyin sayılacağını yapılandırabilirsiniz](general#4-installs-definition-for-analytics).
Anonim kullanıcılar için yüklemeleri **cihaz ID'lerine** göre saymanız gerekir. Bu durumda, yeniden yüklemeler de dahil olmak üzere bir cihazdaki her uygulama yüklemesi bir yükleme olarak sayılır.
## Tanımlanmış kullanıcılar \{#identified-users\}
Kullanıcıları uygulamada tanımlamak için iki seçeneğiniz vardır:
- [**Giriş/kayıt sırasında:**](#during-loginsignup) Kullanıcılar uygulamanız başladıktan sonra oturum açıyorsa, kimlik doğruladıklarında `identify()` metodunu bir customer user ID ile çağırın.
- [**SDK aktivasyonu sırasında:**](#during-the-sdk-activation) Uygulama başlatıldığında zaten depolanmış bir customer user ID'niz varsa, bunu `activate()` çağrısında gönderin.
:::important
Varsayılan olarak, Adapty başka bir Customer User ID ile ilişkilendirilmiş bir Customer User ID'den satın alma aldığında, access level paylaşılır; dolayısıyla her iki profil de ücretli erişime sahip olur. Bu ayarı, ücretli erişimi bir profilden diğerine aktaracak veya paylaşımı tamamen devre dışı bırakacak şekilde yapılandırabilirsiniz. Ayrıntılar için [makaleye](general#6-sharing-paid-access-between-user-accounts) bakın.
:::
### Giriş/kayıt sırasında \{#during-loginsignup\}
Kullanıcıları uygulama başlatıldıktan sonra tanımlıyorsanız (örneğin uygulamanıza giriş yaptıktan veya kaydolduktan sonra), customer user ID'yi ayarlamak için `identify` metodunu kullanın.
- Bu customer user ID'yi **daha önce kullanmadıysanız**, Adapty onu otomatik olarak mevcut profile bağlar.
- Bu customer user ID'yi **daha önce kullanıcıyı tanımlamak için kullandıysanız**, Adapty bu customer user ID ile ilişkili profille çalışmaya geçer.
:::important
Müşteri kullanıcı ID'leri her kullanıcı için benzersiz olmalıdır. Parametreye sabit bir değer atarsanız, tüm kullanıcılar tek bir kullanıcı olarak değerlendirilir.
:::
`identify` metodunu her zaman `await` ile çağırın ve ardından diğer SDK metodlarını kullanın. Eş zamanlı çağrılar `#3006 profileWasChanged` hatasına yol açar veya anonim profil üzerinde işlem yapar. Bkz. [iOS SDK'da çağrı sırası](ios-sdk-call-order).
```swift showLineNumbers
do {
try await Adapty.identify("YOUR_USER_ID") // Her kullanıcı için benzersiz olmalıdır
} catch {
// hatayı işleyin
}
```
```swift showLineNumbers
// Kullanıcı ID'leri her kullanıcı için benzersiz olmalıdır
Adapty.identify("YOUR_USER_ID") { error in
if let error {
// hatayı işleyin
}
}
```
### SDK aktivasyonu sırasında \{#during-the-sdk-activation\}
SDK'yı etkinleştirdiğinizde zaten bir customer user ID biliyorsanız, `identify` metodunu ayrıca çağırmak yerine bunu `activate` metodunda gönderebilirsiniz.
Bir customer user ID bilmenize rağmen bunu yalnızca aktivasyon sonrasında ayarlarsanız, aktivasyonda Adapty yeni bir anonim profil oluşturacak ve siz `identify` metodunu çağırdıktan sonra mevcut profile geçecektir.
Mevcut bir customer user ID (daha önce kullandığınız bir ID) veya yeni bir tane geçirebilirsiniz. Yeni bir tane geçerseniz, aktivasyonda oluşturulan yeni profil otomatik olarak customer user ID'ye bağlanacaktır.
:::note
Varsayılan olarak, anonim profil oluşturma analitik kontrol panellerini etkilemez; çünkü yüklemeler cihaz ID'lerine göre sayılır.
Bir cihaz ID'si, bir cihazdaki mağazadan yapılan tek bir uygulama yüklemesini temsil eder ve yalnızca uygulama yeniden yüklendikten sonra yeniden oluşturulur.
Bu, ilk mi yoksa tekrarlanan bir yükleme mi olduğuna ya da mevcut bir customer user ID'nin kullanılıp kullanılmadığına bağlı değildir.
Profil oluşturma (SDK aktivasyonunda veya çıkış yapılmasında), oturum açma veya uygulamayı yeniden yüklemeden güncelleme, ek yükleme olayları oluşturmaz.
Yüklemeleri cihazlar yerine benzersiz kullanıcılara göre saymak istiyorsanız, **App settings** bölümüne gidin ve [**Installs definition for analytics**](general#4-installs-definition-for-analytics) ayarını yapılandırın.
:::
```swift showLineNumbers
// Place in the app main struct for SwiftUI or in AppDelegate for UIKit
let configurationBuilder =
AdaptyConfiguration
.builder(withAPIKey: "PUBLIC_SDK_KEY")
.with(customerUserId: "YOUR_USER_ID") // Customer user IDs must be unique for each user. If you hardcode the parameter value, all users will be considered as one.
do {
try await Adapty.activate(with: configurationBuilder.build())
} catch {
// handle the error
}
```
```swift showLineNumbers
// Place in the app main struct for SwiftUI or in AppDelegate for UIKit
let configurationBuilder =
AdaptyConfiguration
.builder(withAPIKey: "PUBLIC_SDK_KEY")
.with(customerUserId: "YOUR_USER_ID") // Customer user IDs must be unique for each user. If you hardcode the parameter value, all users will be considered as one.
Adapty.activate(with: configurationBuilder.build()) { error in
// handle the error
}
```
### Kullanıcı oturumunu kapatma \{#log-users-out\}
Kullanıcıların oturumunu kapatmak için bir butonunuz varsa, `logout` metodunu kullanın.
:::important
Kullanıcının oturumunu kapatmak, o kullanıcı için yeni bir anonim profil oluşturur.
:::
```swift showLineNumbers
do {
try await Adapty.logout()
} catch {
// handle the error
}
```
```swift showLineNumbers
Adapty.logout { error in
if error == nil {
// successful logout
}
}
```
:::info
Kullanıcıları tekrar uygulamaya giriş yaptırmak için `identify` metodunu kullanın.
:::
### Giriş yapmadan satın almaya izin verme \{#allow-purchases-without-login\}
Kullanıcılarınız uygulamanıza giriş yapmadan önce ve sonra satın alma yapabiliyorsa, giriş yaptıklarında erişimlerini kaybetmeyeceklerinden emin olmanız gerekir:
1. Oturumu kapalı bir kullanıcı satın alma yaptığında, Adapty bunu anonim profil ID'sine bağlar.
2. Kullanıcı hesabına giriş yaptığında, Adapty tanımlanmış profiliyle çalışmaya geçer.
- Yeni bir customer user ID ise (örneğin satın alma kayıt olmadan önce yapılmışsa), Adapty customer user ID'yi mevcut profile atar; böylece tüm satın alma geçmişi korunur.
- Mevcut bir customer user ID ise (customer user ID zaten bir profile bağlıysa), profil geçişinin ardından gerçek access level'ı almanız gerekir. Tanımlamanın hemen ardından [`getProfile`](ios-check-subscription-status) metodunu çağırabilir veya verinin otomatik olarak senkronize olması için [profil güncellemelerini dinleyebilirsiniz](ios-check-subscription-status).
## Sonraki adımlar \{#next-steps\}
Tebrikler! Uygulamanıza uygulama içi ödeme mantığını başarıyla uyguladınız! Uygulamanızın monetizasyonunda başarılar dileriz!
Adapty'den daha fazla yararlanmak için şu konuları inceleyebilirsiniz:
- [**Test etme**](test-purchases-in-sandbox): Her şeyin beklendiği gibi çalıştığından emin olun
- [**Onboardings**](ios-onboardings): Kullanıcıları onboarding'lerle etkileşime geçirin ve elde tutma oranını artırın
- [**Entegrasyonlar**](configuration): Tek satır kodla pazarlama attribution ve analitik hizmetleriyle entegre edin
- [**Özel profil öznitelikleri ayarlama**](setting-user-attributes): Kullanıcı profillerine özel öznitelikler ekleyin ve segmentler oluşturun; böylece A/B testleri başlatabilir veya farklı kullanıcılara farklı paywall'lar gösterebilirsiniz
---
# File: adapty-sdk-integration-skill
---
---
title: "SDK entegrasyon becerisini kullanarak Adapty'yi iOS uygulamanıza entegre edin"
description: "Adapty SDK'sını iOS uygulamanıza uçtan uca entegre etmek için AI kodlama aracınızla adapty-sdk-integration becerisini kullanın."
---
[adapty-sdk-integration skill](https://github.com/adaptyteam/adapty-sdk-integration-skill), Adapty entegrasyonunu uçtan uca otomatikleştirir: kontrol paneli kurulumu, SDK kurulumu, paywall ve her aşama için doğrulama. Platformunuzu otomatik olarak algılar ve her aşamada ilgili Adapty dokümanlarını getirir.
**Desteklenen araçlar**: Claude Code, GitHub Copilot CLI, OpenAI Codex, Gemini CLI.
Kurulum için aracınıza uygun formu seçin. Tam liste [skill README](https://github.com/adaptyteam/adapty-sdk-integration-skill) dosyasında yer almaktadır.
**Claude Code**
```
claude plugin marketplace add adaptyteam/adapty-sdk-integration-skill
claude plugin install adapty-sdk-integration@adapty
```
**GitHub Copilot CLI**
```
gh skill install adaptyteam/adapty-sdk-integration-skill
```
**Gemini CLI**
```
gemini skills install https://github.com/adaptyteam/adapty-sdk-integration-skill
```
**OpenAI Codex veya başka bir araç** — [skills CLI](https://skills.sh)'yi kullanın (bu şekilde kurulan skill'ler otomatik olarak güncellenmez):
```
npx skills add adaptyteam/adapty-sdk-integration-skill
```
Alternatif olarak, repo'yu klonlayıp `skills/adapty-sdk-integration/` dizinini aracınızın skill'ler klasörüne kopyalayabilirsiniz.
Kurulumdan sonra skill'i projenizde çalıştırın:
```
/adapty-sdk-integration
```
Skill birkaç kurulum sorusu sorar, ardından kontrol paneli kurulumu, SDK kurulumu, paywall ve doğrulama adımlarında sizi yönlendirir.
:::important
Bu özellik beta aşamasındadır. Takılı kalır veya beklenmedik şekilde davranırsa, her aşamada yapay zeka aracınıza doğru dokümanları sunan [adım adım entegrasyon kılavuzunu](adapty-cursor) takip edin.
:::
[adapty-sdk-integration skill](https://github.com/adaptyteam/adapty-sdk-integration-skill), Adapty entegrasyonunu uçtan uca otomatikleştirir: kontrol paneli kurulumu, SDK kurulumu, paywall ve her aşama için doğrulama. Platformunuzu otomatik olarak algılar ve her aşamada ilgili Adapty dokümanlarını getirir.
**Desteklenen araçlar**: Claude Code, GitHub Copilot CLI, OpenAI Codex, Gemini CLI.
Kurulum için aracınıza uygun formu seçin. Tam liste [skill README](https://github.com/adaptyteam/adapty-sdk-integration-skill) dosyasında yer almaktadır.
**Claude Code**
```
claude plugin marketplace add adaptyteam/adapty-sdk-integration-skill
claude plugin install adapty-sdk-integration@adapty
```
**GitHub Copilot CLI**
```
gh skill install adaptyteam/adapty-sdk-integration-skill
```
**Gemini CLI**
```
gemini skills install https://github.com/adaptyteam/adapty-sdk-integration-skill
```
**OpenAI Codex veya başka bir araç** — [skills CLI](https://skills.sh)'yi kullanın (bu şekilde kurulan skill'ler otomatik olarak güncellenmez):
```
npx skills add adaptyteam/adapty-sdk-integration-skill
```
Alternatif olarak, repo'yu klonlayıp `skills/adapty-sdk-integration/` dizinini aracınızın skill'ler klasörüne kopyalayabilirsiniz.
Kurulumdan sonra skill'i projenizde çalıştırın:
```
/adapty-sdk-integration
```
Skill birkaç kurulum sorusu sorar, ardından kontrol paneli kurulumu, SDK kurulumu, paywall ve doğrulama adımlarında sizi yönlendirir.
---
# File: adapty-cursor
---
---
title: "Adapty'yi iOS uygulamanıza AI yardımıyla entegre edin"
description: "Cursor, Context7, ChatGPT, Claude veya diğer AI araçlarını kullanarak Adapty'yi iOS uygulamanıza adım adım entegre etme kılavuzu."
---
Bu rehber, bir yapay zeka kodlama aracı yardımıyla Adapty'yi iOS uygulamanıza adım adım entegre etmenizi sağlar — doğru Adapty dokümanlarını doğru sırayla besleyerek ilerlersiniz.
For a fully automated integration, use the [adapty-sdk-integration skill](https://github.com/adaptyteam/adapty-sdk-integration-skill): it runs the whole integration from your AI coding tool in one command.
## Başlamadan önce: kontrol paneli kurulumu \{#before-you-start-dashboard-setup\}
Adapty, herhangi bir SDK kodu yazmadan önce kontrol panelinde bazı yapılandırmalar gerektiriyor. Bunu etkileşimli bir LLM becerisiyle ya da kontrol paneli üzerinden manuel olarak yapabilirsiniz.
### Beceri yaklaşımı (önerilen) \{#skill-approach-recommended\}
Adapty CLI becerisi, LLM'inizin uygulamanızı, ürünlerinizi, access level'ları, paywall'ları ve placement'ları doğrudan kurmasını sağlar — her adım için kontrol panelini açmanıza gerek kalmaz. Yalnızca [mağazanızı bağlamanız](integrate-payments) gerekir.
```
npx skills add adaptyteam/adapty-cli --skill adapty-cli
```
Beceri eklendikten sonra agent'ınızda `/adapty-cli` komutunu çalıştırın. Mağazanızı bağlamak için kontrol panelini açmanız gereken anlar dahil her adımda sizi yönlendirecektir.
### Kontrol paneli yaklaşımı \{#dashboard-approach\}
Her şeyi manuel olarak yapılandırmayı tercih ediyorsanız, kod yazmadan önce şunlara ihtiyacınız var. LLM'iniz kontrol paneli değerlerini sizin için bulamaz — bunları kendiniz sağlamanız gerekir.
1. **Uygulama mağazanızı bağlayın**: Adapty Kontrol Paneli'nde **App settings → General** sayfasına gidin. Satın almaların çalışması için bu zorunludur.
[App Store'u bağlayın](integrate-payments)
2. **Public SDK anahtarınızı kopyalayın**: Adapty Kontrol Paneli'nde **App settings → General** sayfasına gidin ve **API keys** bölümünü bulun. Kodda bu, `Adapty.activate("YOUR_PUBLIC_SDK_KEY")` çağrısına geçirdiğiniz dizedir.
3. **En az bir ürün oluşturun**: Adapty Kontrol Paneli'nde **Products** sayfasına gidin. Ürünlere koddan doğrudan başvurmazsınız — Adapty bunları flow'lar veya paywall'lar aracılığıyla iletir.
[Ürün ekleyin](quickstart-products)
4. **Bir flow veya paywall ve bir placement oluşturun**: Adapty Kontrol Paneli'nde bir flow (ya da kullanıcı arayüzünü kendiniz oluşturacaksanız bir paywall) oluşturun, ardından **Placements** sayfasında bir placement'a atayın. Kodda, placement ID'si `Adapty.getFlow("YOUR_PLACEMENT_ID")` fonksiyonuna geçirdiğiniz string değerdir.
[Flow oluşturun](quickstart-paywalls)
5. **Access level'ları ayarlayın**: Adapty Kontrol Paneli'nde **Products** sayfasındaki her ürün için yapılandırın. Kodda `profile.accessLevels["premium"]` içinde kontrol edilen dizedir. Varsayılan `premium` access level çoğu uygulama için yeterlidir. Ödeme yapan kullanıcılar ürüne göre farklı özelliklere erişiyorsa (örneğin `basic` plan ile `pro` plan), kod yazmaya başlamadan önce [ek access level'lar oluşturun](assigning-access-level-to-a-product).
:::tip
Bu beşini tamamladığınızda kod yazmaya hazırsınız. LLM'inize şunu söyleyin: "Public SDK anahtarım X, placement ID'm Y" — böylece doğru başlatma ve paywall çekme kodu üretebilir.
:::
### Hazır olduğunuzda yapılandırın \{#set-up-when-ready\}
Kodlamaya başlamak için bunlar zorunlu değil, ancak entegrasyonunuz olgunlaştıkça ihtiyacınız olacak:
- **A/B testleri**: **Placements** sayfasından yapılandırın. Kod değişikliği gerekmez.
[A/B testleri](ab-tests)
- **Ek flow'lar ve placement'lar**: Farklı placement ID'leriyle daha fazla `getFlow` çağrısı ekleyin.
- **Analitik entegrasyonları**: **Integrations** sayfasından yapılandırın. Kurulum entegrasyona göre değişir. Bkz. [analitik entegrasyonları](analytics-integration) ve [attribution entegrasyonları](attribution-integration).
## Adapty dokümanlarını LLM'inize gönderin \{#feed-adapty-docs-to-your-llm\}
### Context7 kullanın (önerilen) \{#use-context7-recommended\}
[Context7](https://context7.com), LLM'inize güncel Adapty dokümantasyonuna doğrudan erişim sağlayan bir MCP sunucusudur. LLM'iniz, ne sorduğunuza göre doğru dokümanları otomatik olarak getirir — manuel URL yapıştırmaya gerek kalmaz.
Context7; **Cursor**, **Claude Code**, **Windsurf** ve diğer MCP uyumlu araçlarla çalışır. Kurmak için şunu çalıştırın:
```
npx ctx7 setup
```
Bu komut editörünüzü algılar ve Context7 sunucusunu yapılandırır. Manuel kurulum için [Context7 GitHub deposuna](https://github.com/upstash/context7) bakın.
Yapılandırıldıktan sonra prompt'larınızda Adapty kütüphanesine başvurun:
```
Use the adaptyteam/adapty-docs library to look up how to install the iOS SDK
```
:::warning
Context7 doküman bağlantılarını manuel olarak yapıştırma ihtiyacını ortadan kaldırsa da uygulama sırası önemlidir. Her şeyin düzgün çalışması için aşağıdaki [uygulama adımlarını](#implementation-walkthrough) sırayla takip edin.
:::
### Düz metin dokümanları kullanın \{#use-plain-text-docs\}
Herhangi bir Adapty dokümanına düz metin Markdown olarak erişebilirsiniz. URL'nin sonuna `.md` ekleyin ya da makale başlığının altındaki **Copy for LLM** düğmesine tıklayın. Örnek: [adapty-cursor.md](https://adapty.io/docs/tr/adapty-cursor.md).
Aşağıdaki [uygulama adımlarının](#implementation-walkthrough) her biri, yapıştırabileceğiniz `.md` bağlantılarıyla bir "LLM'inize gönderin" bloğu içerir.
Aynı anda daha fazla dokümantasyon için aşağıdaki [dizin dosyaları ve platforma özgü alt kümeler](#plain-text-doc-index-files) bölümüne bakın.
## Uygulama adımları \{#implementation-walkthrough\}
Bu kılavuzun geri kalanı, uygulama sırasına göre Adapty entegrasyonunu ele alır. Her aşamada LLM'inize gönderilecek dokümanlar, tamamlandığında görmeniz gerekenler ve sık karşılaşılan sorunlar yer alır.
### Entegrasyonunuzu planlayın \{#plan-your-integration\}
Koda atlamadan önce LLM'inizden projenizi analiz etmesini ve bir uygulama planı oluşturmasını isteyin. AI aracınız bir planlama modunu destekliyorsa (Cursor veya Claude Code'un plan modu gibi), kod yazmadan önce LLM'in hem proje yapınızı hem de Adapty dokümanlarını okuyabilmesi için bu modu kullanın.
LLM'inize satın almalar için hangi yaklaşımı kullandığınızı söyleyin — bu, hangi kılavuzları takip etmesi gerektiğini etkiler:
- [**Adapty Flow Builder**](adapty-flow-builder): Flow'ları Adapty'nin no-code builder'ında oluşturursunuz; SDK bunları otomatik olarak render eder.
- [**Manuel oluşturulan paywalllar**](ios-quickstart-manual): Kendi paywall arayüzünüzü kodla inşa edersiniz, ancak ürünleri getirmek ve satın almaları yönetmek için Adapty'yi kullanırsınız.
- [**Observer mode**](observer-vs-full-mode): Mevcut satın alma altyapınızı korur ve Adapty'yi yalnızca analitik ve entegrasyonlar için kullanırsınız.
Hangisini seçeceğinizden emin değil misiniz? [Hızlı başlangıçtaki karşılaştırma tablosunu](ios-quickstart-paywalls) okuyun.
### SDK'yı yükleyin ve yapılandırın \{#install-and-configure-the-sdk\}
Adapty SDK paketini Xcode'da Swift Package Manager aracılığıyla yükleyin ve Public SDK anahtarınızla etkinleştirin. Bu temeldir — bunu yapmadan hiçbir şey çalışmaz.
**Kılavuz:** [Adapty SDK'yı yükleyin ve yapılandırın](sdk-installation-ios)
LLM'inize gönderin:
```
Read these Adapty docs before writing code:
- https://adapty.io/docs/tr/sdk-installation-ios.md
```
:::tip[Kontrol noktası]
- **Beklenen:** Uygulama derlenir ve çalışır. Xcode konsolu Adapty aktivasyon logunu gösterir.
- **Dikkat:** "Public API key is missing" hatası → placeholder'ı App settings'deki gerçek anahtarınızla değiştirdiğinizi doğrulayın.
:::
### Flow veya paywall gösterme ve satın alma işlemlerini yönetme \{#show-flows-or-paywalls-and-handle-purchases\}
Placement ID'ye göre bir flow veya paywall getirin, görüntüleyin ve satın alma olaylarını yönetin. İhtiyacınız olan kılavuzlar, satın alma işlemlerini nasıl yönettiğinize bağlıdır.
Her satın almayı ilerlerken sandbox'ta test edin — sona bırakmayın. Kurulum talimatları için [Sandbox'ta satın alma testi](test-purchases-in-sandbox) bölümüne bakın.
**Kılavuzlar:**
- [Flow Builder ile satın almaları etkinleştirin (hızlı başlangıç)](ios-quickstart-paywalls)
- [Flow'ları ve yapılandırmalarını alın](get-pb-paywalls)
- [Flow'ları görüntüleyin](ios-present-paywalls)
- [Flow olaylarını yönetin](ios-handling-events)
- [Buton eylemlerine yanıt verin](handle-paywall-actions)
Bu metni LLM'inize gönderin:
```
Kod yazmadan önce şu Adapty dokümanlarını okuyun:
- https://adapty.io/docs/tr/ios-quickstart-paywalls.md
- https://adapty.io/docs/tr/get-pb-paywalls.md
- https://adapty.io/docs/tr/ios-present-paywalls.md
- https://adapty.io/docs/tr/ios-handling-events.md
- https://adapty.io/docs/tr/handle-paywall-actions.md
```
:::tip[Kontrol Noktası]
- **Beklenen:** Flow, yapılandırdığınız ürünlerle birlikte görünür. Bir ürüne dokunmak sandbox satın alma iletişim kutusunu tetikler.
- **Dikkat:** Boş flow veya `getFlow` hatası → placement ID'nin kontrol panelindekiyle birebir eşleştiğini ve placement'a bir kitle atandığını doğrulayın.
:::
**Kılavuzlar:**
- [Özel paywall'ınızda satın almaları etkinleştirme (hızlı başlangıç)](ios-quickstart-manual)
- [Paywall ve ürünleri getirme](fetch-paywalls-and-products)
- [Remote config ile tasarlanmış paywall'ı gösterme](present-remote-config-paywalls)
- [Satın alma yapma](making-purchases)
- [Satın almaları geri yükleme](restore-purchase)
Bu bir dokümantasyon çeviri görevi değil — bu, bir kullanıcının LLM'sine göndermesi için hazırlanmış bir mesajdır. Çevirilecek MDX dokümantasyonu içermediğinden herhangi bir çıktı üretemem.
Lütfen çevirmemi istediğiniz MDX dokümantasyon içeriğini paylaşın.
:::tip[Kontrol Noktası]
- **Beklenen:** Özel paywall'ınız Adapty'den çekilen ürünleri gösteriyor. Bir ürüne dokunmak sandbox satın alma iletişim kutusunu tetikliyor.
- **Dikkat:** Boş ürünler dizisi → paywall'a kontrol panelinde ürün atandığını ve placement'ın bir kitlesi olduğunu doğrulayın.
:::
**Kılavuzlar:**
- [Observer mode'a genel bakış](observer-vs-full-mode)
- [Observer mode'u uygulama](implement-observer-mode)
- [Observer mode'da işlemleri raporlama](report-transactions-observer-mode)
:::tip[Checkpoint]
- **Beklenen:** Mevcut satın alma akışınızı kullanarak sandbox ortamında yapılan bir satın alma işleminin ardından, işlem Adapty kontrol panelindeki **Event Feed** bölümünde görünür.
- **Dikkat:** Hiçbir olay görünmüyorsa → işlemleri Adapty'ye raporladığınızı ve App Store Server Notifications'ın yapılandırıldığını doğrulayın.
:::
### Abonelik durumunu kontrol edin \{#check-subscription-status\}
Satın alma işleminin ardından premium içeriği kısıtlamak için kullanıcı profilinde aktif bir access level olup olmadığını kontrol edin.
**Kılavuz:** [Abonelik durumunu kontrol edin](ios-check-subscription-status)
LLM'inize gönderin:
```
Read these Adapty docs before writing code:
- https://adapty.io/docs/tr/ios-check-subscription-status.md
```
:::tip[Kontrol noktası]
- **Beklenen:** Bir sandbox satın almasının ardından `profile.accessLevels["premium"]?.isActive` değeri `true` döner.
- **Dikkat:** Satın alma sonrası boş `accessLevels` → ürüne kontrol panelinde bir access level atandığını kontrol edin.
:::
### Kullanıcıları tanımlayın \{#identify-users\}
Satın almaların cihazlar arasında saklanabilmesi için uygulama kullanıcı hesaplarınızı Adapty profilleriyle ilişkilendirin.
:::important
Uygulamanızda kimlik doğrulama yoksa bu adımı atlayın.
:::
**Kılavuz:** [Kullanıcıları tanımlayın](ios-quickstart-identify)
LLM'inize gönderin:
```
Read these Adapty docs before writing code:
- https://adapty.io/docs/tr/ios-quickstart-identify.md
```
:::tip[Kontrol noktası]
- **Beklenen:** `Adapty.identify("your-user-id")` çağrısının ardından kontrol paneli **Profiles** bölümü özel kullanıcı ID'nizi gösterir.
- **Dikkat:** Anonim profil attribution sorunlarından kaçınmak için `identify`'ı aktivasyondan sonra ama paywall'ları çekmeden önce çağırın.
:::
### Yayına hazırlanın \{#prepare-for-release\}
Entegrasyonunuz sandbox'ta çalışır hale geldiğinde, her şeyin üretime hazır olduğundan emin olmak için yayın kontrol listesini adım adım geçin.
**Kılavuz:** [Yayın kontrol listesi](release-checklist)
LLM'inize gönderin:
```
Read these Adapty docs before releasing:
- https://adapty.io/docs/tr/release-checklist.md
```
:::tip[Kontrol noktası]
- **Beklenen:** Tüm kontrol listesi maddeleri onaylandı: mağaza bağlantısı, sunucu bildirimleri, satın alma akışı, access level kontrolleri ve gizlilik gereksinimleri.
- **Dikkat:** App Store Server Notifications eksik → bunları **App settings → iOS SDK** bölümünden yapılandırın; aksi halde olaylar kontrol panelinde görünmez.
:::
## Düz metin doküman dizin dosyaları \{#plain-text-doc-index-files\}
LLM'inize tek tek sayfaların ötesinde daha geniş bir bağlam vermeniz gerekirse, tüm Adapty dokümantasyonunu listeleyen veya birleştiren dizin dosyaları sunuyoruz:
- [`llms.txt`](https://adapty.io/docs/tr/llms.txt): `.md` bağlantılarıyla tüm sayfaları listeler. Web sitelerini LLM'lere erişilebilir kılmaya yönelik [gelişmekte olan bir standart](https://llmstxt.org/). Bazı AI agent'lar (örn. ChatGPT) için `llms.txt` dosyasını indirip sohbete yüklemeniz gerekebilir.
- [`llms-full.txt`](https://adapty.io/docs/tr/llms-full.txt): Tüm Adapty dokümantasyon sitesi tek bir dosyada birleştirilmiş hali. Çok büyüktür — yalnızca tam resme ihtiyaç duyduğunuzda kullanın.
- iOS'a özgü [`ios-llms.txt`](https://adapty.io/docs/tr/ios-llms.txt) ve [`ios-llms-full.txt`](https://adapty.io/docs/tr/ios-llms-full.txt): Tam siteye kıyasla token tasarrufu sağlayan platforma özgü alt kümeler.
---
# File: get-pb-paywalls
---
---
title: "Flow ve paywall'ları alma - iOS"
description: "iOS uygulamanızda Adapty'den flow ve paywall'ları getirme."
---
[flow veya Paywall Builder paywall'unuzu tasarladıktan](adapty-paywall-builder) sonra bunu mobil uygulamanızda gösterebilirsiniz. İlk adım, aşağıda açıklandığı gibi placement ile ilişkili flow veya paywall'u ve görünüm yapılandırmasını almaktır.
:::tip
Adapty SDK'nın bir mobil uygulamaya nasıl entegre edildiğine dair gerçek dünya örneği görmek ister misiniz? Tam kurulumu, paywall gösterimi, satın alma işlemleri ve diğer temel işlevleri içeren [örnek uygulamalarımıza](sample-apps) göz atın.
:::
Başlamadan önce
1. Adapty Kontrol Paneli'nde [ürünlerinizi oluşturun](create-product).
2. Adapty Kontrol Paneli'nde [bir flow/paywall oluşturun ve ürünleri ekleyin](create-paywall).
3. Adapty Kontrol Paneli'nde [placement'lar oluşturun ve flow/paywall'ınızı ekleyin](create-placement).
4. Mobil uygulamanıza [Adapty SDK](sdk-installation-ios) kurun.
## Flow/paywall getirme \{#fetch-flowpaywall\}
Flow Builder veya Paywall Builder ile bir flow ya da paywall tasarladıysanız, bunu kullanıcıya göstermek için mobil uygulama kodunuzda nasıl render edileceği konusunda endişelenmenize gerek yok. Bu tür bir flow veya paywall, içinde ne gösterileceğini ve nasıl gösterileceğini zaten içerir. Bununla birlikte, placement aracılığıyla ID'sini, görünüm yapılandırmasını almanız ve ardından mobil uygulamanızda sunmanız gerekir.
Flow veya paywall'ı ve onun [görüntüleme yapılandırmasını](get-pb-paywalls#fetch-the-view-configuration) mümkün olduğunca erken çekin — ideal olarak göstermeden çok önce. Görüntüleme yapılandırmasını çeker çekmez, SDK arka planda görsellerini indirmeye ve önbelleğe almaya başlar. Ne kadar erken çekerseniz, bu indirmelerin tamamlanması için o kadar fazla zaman olur. Flow veya paywall'ı gösterdiğinizde, yapılandırma ve görseller zaten önbellekte hazır olabilir.
Bir flow veya paywall almak için `getFlow` metodunu kullanın:
```swift showLineNumbers
do {
let flow = try await Adapty.getFlow(placementId: "YOUR_PLACEMENT_ID")
// istenen flow/paywall
} catch {
// hatayı işle
}
```
```swift showLineNumbers
Adapty.getFlow(placementId: "YOUR_PLACEMENT_ID") { result in
switch result {
case let .success(flow):
// istenen flow/paywall
case let .failure(error):
// hatayı işle
}
}
```
Parametreler:
| Parametre | Zorunluluk | Açıklama |
|---------|--------|-----------|
| **placementId** | zorunlu | İstenen [Placement](placements)'ın tanımlayıcısı. Adapty Kontrol Paneli'nde bir placement oluştururken belirttiğiniz değerdir. |
| **fetchPolicy** | varsayılan: `.reloadRevalidatingCacheData` |
SDK varsayılan olarak sunucudan veri yüklemeye çalışır; başarısız olursa önbelleğe alınmış veriyi döndürür. Kullanıcılarınızın her zaman en güncel veriye ulaşmasını sağladığından bu seçeneği öneriyoruz.
Ancak kullanıcılarınızın kararsız bir internet bağlantısıyla karşılaştığını düşünüyorsanız, önbellekte veri varsa onu döndürmek için `.returnCacheDataElseLoad` seçeneğini kullanabilirsiniz. Bu durumda kullanıcılar en son veriye ulaşamayabilir, ama internet bağlantısı ne kadar kesintili olursa olsun daha hızlı yükleme süresi yaşarlar. Önbellek düzenli olarak güncellenir; dolayısıyla ağ isteklerini azaltmak için oturum boyunca güvenle kullanılabilir.
Önbelleğin uygulama yeniden başlatıldığında silinmediğini, yalnızca uygulama kaldırıldığında veya manuel temizlik yapıldığında temizlendiğini unutmayın.
Adapty SDK, paywallları yerel olarak iki katmanda saklar: yukarıda açıklanan düzenli güncellenen önbellek ve [yedek paywalllar](fallback-paywalls). Paywallları daha hızlı getirmek için CDN, CDN'e ulaşılamadığı durumlarda ise bağımsız bir yedek sunucu kullanıyoruz. Bu sistem, internet bağlantısının yetersiz olduğu durumlarda bile güvenilirliği sağlarken paywalllarınızın her zaman en güncel halini almanızı garanti edecek şekilde tasarlanmıştır.
|
| **loadTimeout** | varsayılan: 5 sn |
Bu değer, metodun zaman aşımı süresini sınırlar. Zaman aşımına ulaşılırsa önbelleğe alınmış veri veya yerel yedek döndürülür.
Arka planda işlem farklı isteklerden oluşabileceğinden, nadir durumlarda bu metodun `loadTimeout` ile belirtilen süreden biraz daha geç zaman aşımına uğrayabileceğini unutmayın.
|
Yanıt parametreleri:
| Parametre | Açıklama |
| :-------- | :---------- |
| Flow | Placement, tanımlayıcılar (`id`, `variationId`), ad, remote config'ler ve flow'un bir görünüm yapılandırması içerip içermediğini belirten `hasViewConfiguration` bayrağını barındıran bir `AdaptyFlow` nesnesi. Ürünleri ön yükleme, özel kullanıcı arayüzü veya programatik kontroller için getirmek üzere `getPaywallProducts(flow:)` çağırın. |
## Görünüm yapılandırmasını getir \{#fetch-the-view-configuration\}
Flow veya paywallı getirdikten sonra, `flow.hasViewConfiguration` ile görünüm yapılandırması içerip içermediğini kontrol edin. Bu bayrak, placement'ın Adapty Kontrol Paneli'nde nasıl tasarlandığını ayırt eder:
- **`true`** — placement, **Flow Builder** (bir flow) veya **Paywall Builder** (bir paywall) kullanılarak tasarlanmış. Adapty arayüzü sizin için render eder. Görünüm yapılandırmasını getirmek ve [flow veya paywallı sunmak](ios-present-paywalls) için aşağıdaki adımlarla devam edin.
- **`false`** — placement, Builder arayüzü olmayan özel bir paywall.
`getFlowConfiguration` yöntemini kullanarak görünüm yapılandırmasını yükleyin.
```swift showLineNumbers
guard flow.hasViewConfiguration else {
// handle as remote config paywall
return
}
let flowConfiguration = try await AdaptyUI.getFlowConfiguration(forFlow: flow)
```
Parametreler:
| Parametre | Varlık | Açıklama |
| :----------------------- | :------------- | :---------- |
| **forFlow** | zorunlu | `Adapty.getFlow` aracılığıyla elde edilen bir `AdaptyFlow` nesnesi. |
| **locale** |
isteğe bağlı
varsayılan: `nil`
| [Paywall yerelleştirmesinin](add-paywall-locale-in-adapty-paywall-builder) tanımlayıcısı. `-` ile ayrılmış bir veya iki alt etiket içeren dil kodu olarak beklenir (örn. `en`, `pt-br`). Bkz. [Yerelleştirmeler ve yerel ayar kodları](localizations-and-locale-codes). |
| **loadTimeout** | varsayılan: 5 sn | Bu değer, metodun zaman aşımı süresini sınırlar. Zaman aşımına ulaşılırsa önbelleğe alınmış veri veya yerel yedek döndürülür. Nadir durumlarda bu metod, arka planda farklı isteklerden oluşabileceğinden `loadTimeout`'ta belirtilenden biraz daha geç zaman aşımına uğrayabilir. |
| **products** | isteğe bağlı | Ekranda ürünlerin gösterim zamanlamasını optimize etmek için bir `AdaptyPaywallProduct` nesneleri dizisi sağlayın. `nil` geçilirse AdaptyUI gerekli ürünleri otomatik olarak getirir. |
| **systemRequestsHandler** | isteğe bağlı | Flow aksiyonları tarafından tetiklenen sistem izni ve inceleme isteklerini yöneten, `AdaptySystemRequestsHandler` protokolüne uyan bir nesne. Yalnızca flow'unuz bu tür aksiyonlar içeriyorsa gereklidir. |
| **assetsResolver** | isteğe bağlı | Flow/paywall içindeki resim ve videoları geçersiz kılan bir `[String: AdaptyCustomAsset]` sözlüğü. Bkz. [Varlıkları özelleştir](#customize-assets). |
| **timerResolver** | isteğe bağlı | Geliştirici tanımlı zamanlayıcılar için bitiş tarihlerini sağlayan, `AdaptyTimerResolver` protokolüne uyan bir nesne. Bkz. [Geliştirici tanımlı zamanlayıcıları ayarla](#set-up-developer-defined-timers). |
Yüklendikten sonra, [flow/paywall'ı gösterin](ios-present-paywalls).
## Varsayılan kitle için bir flow veya paywall alarak daha hızlı yükleme sağlayın \{#get-a-flow-or-paywall-for-a-default-audience-to-fetch-it-faster\}
Genellikle flow'lar ve paywall'lar neredeyse anında yüklenir, dolayısıyla bu süreci hızlandırmak için özel bir şey yapmanız gerekmez. Ancak çok sayıda kitle ve placement'ınız varsa ve kullanıcılarınızın internet bağlantısı zayıfsa, bir flow veya paywall'ın yüklenmesi istediğinizden daha uzun sürebilir. Böyle durumlarda, hiçbir şey göstermek yerine pürüzsüz bir kullanıcı deneyimi sunmak amacıyla varsayılan bir flow veya paywall görüntülemek isteyebilirsiniz.
Bu sorunu çözmek için, belirtilen placement'ın **All Users** kitlesi için flow veya paywall'ı getiren `getFlowForDefaultAudience` metodunu kullanabilirsiniz. Ancak, önerilen yaklaşımın `getFlow` metoduyla flow veya paywall getirmek olduğunu unutmamak önemlidir. Bu konuda yukarıdaki [Paywall Bilgilerini Getirme](get-pb-paywalls#fetch-paywall-designed-with-paywall-builder) bölümüne bakabilirsiniz.
:::warning
`getFlow` kullanmanızı neden öneriyoruz
`getFlowForDefaultAudience` metodunun birkaç önemli dezavantajı vardır:
- **Olası geriye dönük uyumluluk sorunları**: Farklı uygulama sürümleri (mevcut ve gelecekteki) için farklı paywall'lar göstermeniz gerekiyorsa bazı zorluklarla karşılaşabilirsiniz. Ya mevcut (eski) sürümü destekleyen paywall'lar tasarlamanız ya da mevcut (eski) sürüme sahip kullanıcıların render edilemeyen paywall'larla sorun yaşayabileceğini kabul etmeniz gerekecektir.
- **Hedeflemenin kaybı**: Tüm kullanıcılar **All Users** kitlesi için tasarlanmış aynı paywall'u görecektir; bu da ülkelere, pazarlama attribution'ına veya kendi özel özniteliklerinize dayalı kişiselleştirilmiş hedeflemeyi kaybetmeniz anlamına gelir.
Bu dezavantajları göze alarak daha hızlı flow veya paywall yükleme avantajından yararlanmak istiyorsanız, `getFlowForDefaultAudience` metodunu aşağıdaki gibi kullanın. Aksi takdirde [yukarıda](get-pb-paywalls#fetch-paywall-designed-with-paywall-builder) anlatılan `getFlow` metodunu kullanmaya devam edin.
:::
```swift showLineNumbers
Adapty.getFlowForDefaultAudience(placementId: "YOUR_PLACEMENT_ID") { result in
switch result {
case let .success(flow):
// the requested flow
case let .failure(error):
// handle the error
}
}
```
| Parametre | Zorunluluk | Açıklama |
|---------|--------|-----------|
| **placementId** | zorunlu | [Placement](placements) tanımlayıcısı. Adapty Kontrol Paneli'nde placement oluştururken belirttiğiniz değerdir. |
| **fetchPolicy** | varsayılan: `.reloadRevalidatingCacheData` |
SDK varsayılan olarak sunucudan veri yüklemeye çalışır; başarısız olursa önbellekteki veriyi döndürür. Kullanıcılarınızın her zaman en güncel verilere ulaşmasını sağladığı için bu seçeneği öneriyoruz.
Ancak kullanıcılarınızın internet bağlantısının kararsız olduğunu düşünüyorsanız, önbellekte veri varsa onu döndürmek için `.returnCacheDataElseLoad` seçeneğini kullanabilirsiniz. Bu durumda kullanıcılar en son verilere ulaşamayabilir; ancak internet bağlantısı ne kadar kötü olursa olsun daha hızlı yükleme süreleri yaşarlar. Önbellek düzenli olarak güncellenir; bu nedenle oturum sırasında gereksiz ağ isteklerinden kaçınmak için önbelleği kullanmak güvenlidir.
Önbellek, uygulama yeniden başlatıldığında temizlenmez; yalnızca uygulama kaldırılıp yeniden yüklendiğinde veya manuel olarak temizlendiğinde sıfırlanır.
|
## Varlıkları özelleştirme \{#customize-assets\}
Paywall/flow'unuzdaki görsel ve videoları özelleştirmek için özel varlıkları uygulayın.
Hero görseller ve videolar önceden tanımlanmış ID'lere sahiptir: `hero_image` ve `hero_video`. Özel bir varlık paketinde, bu öğeleri ID'leri aracılığıyla hedefleyerek davranışlarını özelleştirebilirsiniz.
Diğer görseller ve videolar için Adapty kontrol panelinde [özel bir ID ayarlamanız](custom-media) gerekir.
Örneğin şunları yapabilirsiniz:
- Bazı kullanıcılara farklı bir görsel veya video göster.
- Uzaktan yüklenen ana görsel yüklenirken yerel bir önizleme görseli göster.
- Video oynatılmadan önce bir önizleme görseli göster.
- Oynatıcının video yüklenmeden önce düzen alanını ayırabilmesi için videonun piksel çözünürlüğünü belirt (en-boy oranı = `width / height`). Atlamak için `nil` geçir.
Aşağıda, özel varlıkları basit bir sözlük aracılığıyla nasıl sağlayabileceğine dair bir örnek yer alıyor:
```swift showLineNumbers
let customAssets: [String: AdaptyCustomAsset] = [
// Show a local image using a custom ID
"custom_image": .image(
.uiImage(value: UIImage(named: "image_name")!)
),
// Show a local preview image while a remote main image is loading
"hero_image": .image(
.remote(
url: URL(string: "https://example.com/image.jpg")!,
preview: UIImage(named: "preview_image")
)
),
// Show a local video with a preview image and a known resolution
"hero_video": .video(
.file(
url: Bundle.main.url(forResource: "custom_video", withExtension: "mp4")!,
preview: .uiImage(value: UIImage(named: "video_preview")!),
resolution: CGSize(width: 1080, height: 1920)
)
),
]
let flowConfig = try await AdaptyUI.getFlowConfiguration(
forFlow: flow,
assetsResolver: customAssets
)
```
:::note
Bir öğe bulunamazsa, paywall/flow varsayılan görünümüne geri döner.
:::
## Geliştirici tanımlı zamanlayıcıları ayarlama \{#set-up-developer-defined-timers\}
Mobil uygulamanızda özel zamanlayıcılar kullanmak için `AdaptyTimerResolver` protokolünü uygulayan bir nesne oluşturun. Bu nesne, her özel zamanlayıcının nasıl render edileceğini tanımlar. İsterseniz bu protokole zaten uyan bir `[String: Date]` sözlüğünü doğrudan kullanabilirsiniz. İşte bir örnek:
```swift showLineNumbers
@MainActor
struct AdaptyTimerResolverImpl: AdaptyTimerResolver {
func timerEndAtDate(for timerId: String) -> Date {
switch timerId {
case "CUSTOM_TIMER_6H":
Date(timeIntervalSinceNow: 3600.0 * 6.0) // 6 hours
case "CUSTOM_TIMER_NY":
Calendar.current.date(from: DateComponents(year: 2025, month: 1, day: 1)) ?? Date(timeIntervalSinceNow: 3600.0)
default:
Date(timeIntervalSinceNow: 3600.0) // 1 hour
}
}
}
```
Bu örnekte, `CUSTOM_TIMER_NY` ve `CUSTOM_TIMER_6H`, Adapty Kontrol Paneli'nde ayarladığınız geliştirici tanımlı zamanlayıcıların **Timer ID**'leridir. `timerResolver`, uygulamanızın her zamanlayıcıyı doğru değerle dinamik olarak güncellemesini sağlar. Örneğin:
- `CUSTOM_TIMER_NY`: Zamanlayıcının bitiş anına, örneğin Yılbaşı'na kadar kalan süre.
- `CUSTOM_TIMER_6H`: Kullanıcı paywall'ı açtığında başlayan 6 saatlik sürede kalan zaman.
[Adapty Kontrol Paneli'nde Paywall Builder ile paywallınızın görsel kısmını tasarladıktan sonra](adapty-paywall-builder), bunu mobil uygulamanızda gösterebilirsiniz. İlk adım, aşağıda açıklandığı gibi placement ile ilişkilendirilmiş paywall'ı ve görünüm yapılandırmasını almaktır.
Bu konunun Paywall Builder ile özelleştirilmiş paywalllar için geçerli olduğunu unutmayın. Paywalllarınızı manuel olarak uyguluyorsanız, [Remote config paywalllar için paywallları ve ürünleri getirme](fetch-paywalls-and-products) bölümüne bakın.
:::tip
Mobil uygulamanızda Adapty SDK'nın gerçek bir entegrasyonunu görmek ister misiniz? Tam kurulumu, paywall gösterimi, satın alma işlemleri ve diğer temel işlevleri gösteren [örnek uygulamalarımıza](sample-apps) göz atın.
:::
Mobil uygulamanızda paywall göstermeye başlamadan önce
1. Adapty Kontrol Paneli'nde [ürünlerinizi oluşturun](create-product).
2. Adapty Kontrol Paneli'nde [bir paywall oluşturun ve ürünlerinizi buna ekleyin](create-paywall).
3. Adapty Kontrol Paneli'nde [placement'lar oluşturun ve paywall'ınızı bunlara ekleyin](create-placement).
4. Mobil uygulamanıza [Adapty SDK](sdk-installation-ios)'yı yükleyin.
## Paywall Builder ile tasarlanan paywallı getirme \{#fetch-paywall-designed-with-paywall-builder\}
[Paywall Builder kullanarak bir paywall tasarladıysanız](adapty-paywall-builder), onu kullanıcıya göstermek için mobil uygulama kodunuzda ayrıca render etmenize gerek yoktur. Böyle bir paywall, hem paywallda neyin gösterileceğini hem de nasıl gösterileceğini içerir. Bununla birlikte, ID'sini placement aracılığıyla, görünüm yapılandırmasını ise ayrıca almanız ve ardından uygulamanızda sunmanız gerekir.
En iyi performansı sağlamak için, kullanıcıya sunmadan önce görsellerin indirilmesine yeterince zaman tanımak amacıyla paywallı ve [görünüm yapılandırmasını](get-pb-paywalls#fetch-the-view-configuration-of-paywall-designed-using-paywall-builder) mümkün olduğunca erken almanız önemlidir.
Paywall almak için `getPaywall` metodunu kullanın:
```swift showLineNumbers
do {
let paywall = try await Adapty.getPaywall("YOUR_PLACEMENT_ID")
// the requested paywall
} catch {
// handle the error
}
```
```swift showLineNumbers
Adapty.getPaywall(placementId: "YOUR_PLACEMENT_ID", locale: "en") { result in
switch result {
case let .success(paywall):
// the requested paywall
case let .failure(error):
// handle the error
}
}
```
Parametreler:
| Parametre | Zorunluluk | Açıklama |
|---------|--------|-----------|
| **placementId** | zorunlu | İstenen [Placement](placements) kimliği. Bu, Adapty Kontrol Paneli'nde placement oluştururken belirttiğiniz değerdir. |
| **locale** |
isteğe bağlı
varsayılan: `en`
|
[Paywall yerelleştirmesinin](add-paywall-locale-in-adapty-paywall-builder) kimliği. Bu parametrenin, eksi (**-**) karakteriyle ayrılmış bir veya iki alt etiketten oluşan bir dil kodu olması beklenir. İlk alt etiket dil, ikincisi ise bölge içindir.
Örnek: `en` İngilizce, `pt-br` ise Brezilya Portekizcesini temsil eder.
Yerel ayar kodları ve bunların nasıl kullanılması gerektiği hakkında daha fazla bilgi için bkz. [Yerelleştirmeler ve yerel ayar kodları](localizations-and-locale-codes).
SDK varsayılan olarak sunucudan veri yüklemeye çalışır ve başarısız olması durumunda önbellekteki veriyi döndürür. Kullanıcılarınızın her zaman en güncel veriyi almasını sağladığından bu seçeneği öneriyoruz.
Ancak kullanıcılarınızın kararsız bir internet bağlantısıyla uğraştığını düşünüyorsanız, önbellekte veri varsa döndürmek için `.returnCacheDataElseLoad` kullanmayı değerlendirin. Bu senaryoda kullanıcılar en güncel veriyi almayabilir, ancak internet bağlantısı ne kadar kötü olursa olsun daha hızlı yükleme süreleri yaşarlar. Önbellek düzenli olarak güncellenir, bu nedenle ağ isteklerini azaltmak için oturum sırasında kullanmak güvenlidir.
Önbelleğin uygulama yeniden başlatıldığında silinmediğini; yalnızca uygulama kaldırılıp yeniden yüklendiğinde veya manuel temizlik yapıldığında temizlendiğini unutmayın.
Adapty SDK, paywallları yerel olarak iki katmanda saklar: yukarıda açıklanan düzenli güncellenen önbellek ve [yedek paywalllar](fallback-paywalls). Paywallları daha hızlı getirmek için CDN, CDN'e ulaşılamadığı durumlarda ise bağımsız bir yedek sunucu kullanırız. Bu sistem, internet bağlantısının kısıtlı olduğu durumlarda bile güvenilirliği sağlarken her zaman en güncel paywall sürümünü almanızı garanti etmek için tasarlanmıştır.
|
| **loadTimeout** | varsayılan: 5 sn |
Bu değer, metodun zaman aşımını sınırlar. Zaman aşımına ulaşılırsa önbelleğe alınmış veri veya yerel yedek döndürülür.
İşlemin arka planda farklı isteklerden oluşabileceği nadir durumlarda bu metodun `loadTimeout`'ta belirtilenden biraz daha geç zaman aşımına uğrayabileceğini unutmayın.
|
Yanıt parametreleri:
| Parametre | Açıklama |
| :-------- | :---------- |
| Paywall | Ürün ID'lerinin listesini, paywall tanımlayıcısını, remote config'i ve diğer çeşitli özellikleri içeren bir [`AdaptyPaywall`](https://swift.adapty.io/documentation/adapty/adaptypaywall) nesnesi. |
## Paywall Builder ile tasarlanmış paywallın görünüm yapılandırmasını çekme \{#fetch-the-view-configuration-of-paywall-designed-using-paywall-builder\}
:::important
Paywall Builder'da **Show on device** geçişinin etkin olduğundan emin olun. Bu seçenek açık değilse görünüm yapılandırması çekilemez.
:::
Paywall'ı çektikten sonra, Paywall Builder kullanılarak oluşturulduğunu gösteren bir görünüm yapılandırması içerip içermediğini kontrol edin. Bu, paywall'ı nasıl göstereceğiniz konusunda size rehberlik eder. Görünüm yapılandırması mevcutsa Paywall Builder paywall'ı olarak ele alın; değilse [remote config paywall'ı olarak işleyin](present-remote-config-paywalls).
Görünüm yapılandırmasını yüklemek için `getPaywallConfiguration` metodunu kullanın.
```swift showLineNumbers
guard paywall.hasViewConfiguration else {
// use your custom logic
return
}
do {
let paywallConfiguration = try await AdaptyUI.getPaywallConfiguration(
forPaywall: paywall,
products: products
)
// use loaded configuration
} catch {
// handle the error
}
```
Parametreler:
| Parametre | Zorunluluk | Açıklama |
| :----------------------- | :------------- | :---------- |
| **paywall** | zorunlu | İstenen paywall için controller almak üzere kullanılan `AdaptyPaywall` nesnesi. |
| **loadTimeout** | varsayılan: 5 sn | Bu metot için zaman aşımı sınırını belirler. Zaman aşımına ulaşıldığında önbelleğe alınmış veri veya yerel yedek döndürülür. İşlem arka planda birden fazla istekten oluşabileceğinden, bu metot nadir durumlarda `loadTimeout` içinde belirtilenden biraz daha geç zaman aşımına uğrayabilir. |
| **products** | isteğe bağlı | Ekranda ürünlerin görüntülenme süresini optimize etmek için `AdaptyPaywallProduct` nesnelerinden oluşan bir dizi sağlayın. `nil` geçilirse AdaptyUI gerekli ürünleri otomatik olarak getirir. |
:::note
Birden fazla dil kullanıyorsanız, [Paywall Builder yerelleştirmesi](add-paywall-locale-in-adapty-paywall-builder) eklemeyi ve yerel ayar kodlarını doğru kullanmayı [burada](localizations-and-locale-codes) öğrenin.
:::
Yüklendikten sonra [paywallı sunun](ios-present-paywalls).
## Daha hızlı getirmek için varsayılan kitle paywallını alma \{#get-a-paywall-for-a-default-audience-to-fetch-it-faster\}
Paywalllar genellikle neredeyse anında getirilir, bu nedenle bu süreci hızlandırmak konusunda endişelenmenize gerek yoktur. Ancak çok sayıda kitle ve paywalliniz varsa ve kullanıcılarınızın internet bağlantısı zayıfsa, paywall getirme işlemi istediğinizden daha uzun sürebilir. Bu gibi durumlarda, hiç paywall göstermemek yerine sorunsuz bir kullanıcı deneyimi sağlamak için varsayılan bir paywall görüntülemek isteyebilirsiniz.
Bunu çözmek için, belirtilen placement'ın **All Users** kitlesine ait paywall'unu getiren `getPaywallForDefaultAudience` metodunu kullanabilirsiniz. Ancak önerilen yaklaşımın, yukarıdaki [Paywall Bilgisini Getirme](get-pb-paywalls#fetch-paywall-designed-with-paywall-builder) bölümünde ayrıntılı olarak açıklandığı gibi `getPaywall` metoduyla paywall getirmek olduğunu bilmek önemlidir.
:::warning
Neden `getPaywall` kullanmanızı öneriyoruz
`getPaywallForDefaultAudience` metodunun birkaç önemli dezavantajı vardır:
- **Olası geriye dönük uyumluluk sorunları**: Farklı uygulama sürümleri (mevcut ve gelecekteki) için farklı paywalllar göstermeniz gerekiyorsa zorluklarla karşılaşabilirsiniz. Ya mevcut (eski) sürümü destekleyen paywalllar tasarlamak zorunda kalırsınız ya da mevcut (eski) sürüme sahip kullanıcıların render edilmemiş paywalllarla sorun yaşamasını kabul etmek durumunda kalırsınız.
- **Hedefleme kaybı**: Tüm kullanıcılar **Tüm Kullanıcılar** kitlesi için tasarlanmış aynı paywallı görür; bu da kişiselleştirilmiş hedeflemeyi (ülkelere, pazarlama attribution'ına veya kendi özel niteliklerinize göre) kaybetmeniz anlamına gelir.
Daha hızlı paywall getirme avantajından yararlanmak için bu dezavantajları kabul etmeye hazırsanız, aşağıdaki gibi `getPaywallForDefaultAudience` metodunu kullanın. Aksi takdirde [yukarıda](get-pb-paywalls#fetch-paywall-designed-with-paywall-builder) açıklanan `getPaywall` metodunu tercih edin.
:::
```swift showLineNumbers
Adapty.getPaywallForDefaultAudience(placementId: "YOUR_PLACEMENT_ID", locale: "en") { result in
switch result {
case let .success(paywall):
// the requested paywall
case let .failure(error):
// handle the error
}
}
```
:::note
`getPaywallForDefaultAudience` metodu iOS SDK 2.11.2 sürümünden itibaren kullanılabilir.
:::
| Parametre | Zorunluluk | Açıklama |
|---------|--------|-----------|
| **placementId** | zorunlu | [Placement](placements) kimliği. Bu, Adapty Kontrol Paneli'nde placement oluştururken belirttiğiniz değerdir. |
| **locale** |
isteğe bağlı
varsayılan: `en`
|
[Paywall yerelleştirmesinin](add-remote-config-locale) kimliği. Bu parametrenin, eksi (**-**) karakteriyle ayrılmış bir veya daha fazla alt etiketten oluşan bir dil kodu olması beklenir. İlk alt etiket dil, ikincisi ise bölge içindir.
Örnek: `en` İngilizce, `pt-br` ise Brezilya Portekizcesini temsil eder.
Yerel ayar kodları ve bunların nasıl kullanılması gerektiği hakkında daha fazla bilgi için bkz. [Yerelleştirmeler ve yerel ayar kodları](localizations-and-locale-codes).
SDK varsayılan olarak sunucudan veri yüklemeye çalışır ve başarısız olması durumunda önbellekteki veriyi döndürür. Kullanıcılarınızın her zaman en güncel veriyi almasını sağladığından bu seçeneği öneriyoruz.
Ancak kullanıcılarınızın kararsız bir internet bağlantısıyla uğraştığını düşünüyorsanız, önbellekte veri varsa döndürmek için `.returnCacheDataElseLoad` kullanmayı değerlendirin. Bu senaryoda kullanıcılar en güncel veriyi almayabilir, ancak internet bağlantısı ne kadar kötü olursa olsun daha hızlı yükleme süreleri yaşarlar. Önbellek düzenli olarak güncellenir, bu nedenle ağ isteklerini azaltmak için oturum sırasında kullanmak güvenlidir.
Önbelleğin uygulama yeniden başlatıldığında silinmediğini; yalnızca uygulama kaldırılıp yeniden yüklendiğinde veya manuel temizlik yapıldığında temizlendiğini unutmayın.
|
## Varlıkları özelleştirme \{#customize-assets\}
Paywallınızdaki görselleri ve videoları özelleştirmek için özel varlıkları uygulayın.
Hero görseller ve videolar önceden tanımlanmış ID'lere sahiptir: `hero_image` ve `hero_video`. Özel bir varlık paketinde, bu öğeleri ID'leriyle hedefler ve davranışlarını özelleştirirsiniz.
Diğer görseller ve videolar için Adapty kontrol panelinde [özel bir ID belirlemeniz](custom-media) gerekir.
Örneğin şunları yapabilirsiniz:
- Bazı kullanıcılara farklı bir görsel veya video göstermek.
- Uzak ana görsel yüklenirken yerel bir önizleme görseli göstermek.
- Bir video başlamadan önce önizleme görseli göstermek.
:::important
Bu özelliği kullanmak için Adapty iOS SDK'yı 3.7.0 veya daha yüksek bir sürüme güncelleyin.
:::
Özel varlıkları basit bir sözlük aracılığıyla nasıl sağlayabileceğinize dair bir örnek:
```swift showLineNumbers
let customAssets: [String: AdaptyCustomAsset] = [
// Özel bir kimlik kullanarak yerel bir görsel göster
"custom_image": .image(
.uiImage(value: UIImage(named: "image_name")!)
),
// Uzak ana görsel yüklenirken yerel bir önizleme görseli göster
"hero_image": .image(
.remote(
url: URL(string: "https://example.com/image.jpg")!,
preview: UIImage(named: "preview_image")
)
),
// Önizleme görseli olan yerel bir video göster
"hero_video": .video(
.file(
url: Bundle.main.url(forResource: "custom_video", withExtension: "mp4")!,
preview: .uiImage(value: UIImage(named: "video_preview")!)
)
),
]
let paywallConfig = try await AdaptyUI.getPaywallConfiguration(
forPaywall: paywall,
assetsResolver: customAssets
)
```
:::note
Bir varlık bulunamazsa paywall varsayılan görünümüne geri döner.
:::
## Geliştirici tanımlı zamanlayıcıları ayarlama \{#set-up-developer-defined-timers\}
Mobil uygulamanızda özel zamanlayıcılar kullanmak için `AdaptyTimerResolver` protokolünü uygulayan bir nesne oluşturun. Bu nesne, her özel zamanlayıcının nasıl görüntüleneceğini tanımlar. Tercih ederseniz, bu protokole zaten uygun olduğu için doğrudan bir `[String: Date]` sözlüğü de kullanabilirsiniz. İşte bir örnek:
```swift showLineNumbers
@MainActor
struct AdaptyTimerResolverImpl: AdaptyTimerResolver {
func timerEndAtDate(for timerId: String) -> Date {
switch timerId {
case "CUSTOM_TIMER_6H":
Date(timeIntervalSinceNow: 3600.0 * 6.0) // 6 saat
case "CUSTOM_TIMER_NY":
Calendar.current.date(from: DateComponents(year: 2025, month: 1, day: 1)) ?? Date(timeIntervalSinceNow: 3600.0)
default:
Date(timeIntervalSinceNow: 3600.0) // 1 saat
}
}
}
```
Bu örnekte, `CUSTOM_TIMER_NY` ve `CUSTOM_TIMER_6H`, Adapty Kontrol Paneli'nde ayarladığınız geliştirici tanımlı zamanlayıcıların **Timer ID**'leridir. `timerResolver`, uygulamanızın her zamanlayıcıyı doğru değerle dinamik olarak güncellemesini sağlar. Örneğin:
- `CUSTOM_TIMER_NY`: Yılbaşı gibi zamanlayıcının bitiş anına kadar kalan süre.
- `CUSTOM_TIMER_6H`: Kullanıcının paywall'ı açtığı andan itibaren başlayan 6 saatlik sürede kalan zaman.
---
# File: ios-present-paywalls
---
---
title: "Flow ve paywallları görüntüleme - iOS"
description: "iOS uygulamanızda kullanıcılara flow ve paywallları sunun."
---
Bir flow veya paywall oluştturduysanız, bunu kullanıcıya göstermek için mobil uygulama kodunuzda ayrıca render etmenize gerek yok. Söz konusu flow veya paywall, içinde neyin gösterileceğini ve nasıl gösterileceğini zaten içeriyor.
Aşağıda kullanılan `AdaptyUI.FlowConfiguration` nesnesini edinmek için [Flow ve paywallları getir](get-pb-paywalls) sayfasına bakın.
## SwiftUI'da flow ve paywallları sunma \{#present-flows-and-paywalls-in-swiftui\}
### Ekranda modal görünüm olarak göster \{#present-as-a-modal-view\}
Bir flow veya paywall'ı cihaz ekranında modal görünüm olarak göstermek için SwiftUI'da `.flow` modifier'ını kullanın. En temel çağrı; `isPresented`, `flowConfiguration` ve beş zorunlu callback'i gerektirir:
```swift showLineNumbers title="SwiftUI"
.flow(
isPresented: $flowPresented,
flowConfiguration: ,
didFinishPurchase: { _, _ in /* dismiss, or do nothing to let the flow continue */ },
didFailPurchase: { _, _ in /* handle the error */ },
didFinishRestore: { _ in /* check access level and dismiss */ },
didFailRestore: { _ in /* handle the error */ },
didReceiveError: { _ in flowPresented = false }
)
```
Daha fazla kontrol için, buton tıklamalarını yönetmek amacıyla `didPerformAction` gibi isteğe bağlı callback'ler ekleyin:
```swift showLineNumbers title="SwiftUI"
@State var flowPresented = false // ensure that you manage this variable state and set it to `true` at the moment you want to show the flow or paywall
var body: some View {
Text("Hello, AdaptyUI!")
.flow(
isPresented: $flowPresented,
flowConfiguration: ,
didPerformAction: { action in
switch action {
case .close:
flowPresented = false
default:
// Handle other actions
break
}
},
didFinishPurchase: { product, purchaseResult in /* dismiss, or do nothing to let the flow continue */ },
didFailPurchase: { product, error in /* handle the error */ },
didFinishRestore: { profile in /* check access level and dismiss */ },
didFailRestore: { error in /* handle the error */ },
didReceiveError: { error in flowPresented = false }
)
}
```
(empty input — nothing to translate)
| Parametre | Zorunlu | Açıklama |
|:-----------------------|:---------|:---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| **isPresented** | zorunlu | Flow veya paywall ekranının görüntülenip görüntülenmediğini yöneten bir binding. |
| **flowConfiguration** | zorunlu | Flow veya paywallın görsel ayrıntılarını içeren bir `AdaptyUI.FlowConfiguration` nesnesi. `AdaptyUI.getFlowConfiguration(forFlow:)` metodunu kullanın. Daha fazla bilgi için [Flow ve paywall'ları alma](get-pb-paywalls) bölümüne bakın. |
| **didFinishPurchase** | zorunlu | `Adapty.makePurchase()` başarıyla tamamlandığında çağrılır. Flow otomatik olarak kapanmaz — burada sunum binding'inizi `false` olarak ayarlayabilir ya da hiçbir şey yapmayarak flow'un satın alma sonrasında devam etmesine izin verebilirsiniz. |
| **didFailPurchase** | zorunlu | `Adapty.makePurchase()` başarısız olduğunda çağrılır. |
| **didFinishRestore** | zorunlu | `Adapty.restorePurchases()` başarıyla tamamlandığında çağrılır. |
| **didFailRestore** | zorunlu | `Adapty.restorePurchases()` başarısız olduğunda çağrılır. |
| **didReceiveError** | zorunlu | Bir render hatası veya flow scriptinden kaynaklanan bir çalışma zamanı hatası için çağrılır (örneğin, bir JavaScript istisnası, `AdaptyUIError` kodu `4105`). Render hataları için [Adapty Destek](mailto:support@adapty.io) ile iletişime geçin. |
| **fullScreen** | isteğe bağlı | Flow veya paywallın tam ekran modunda mı yoksa sayfa olarak mı görüneceğini belirler. Varsayılan değer `true`'dur. |
| **didAppear** | isteğe bağlı | Flow veya paywall görünümü sunulduğunda çağrılır. |
| **didDisappear** | isteğe bağlı | Flow veya paywall görünümü kapatıldığında çağrılır. |
| **didPerformAction** | isteğe bağlı | Kullanıcı bir butona tıkladığında çağrılır. `close` ve `openURL` olmak üzere iki action ID önceden tanımlanmıştır; diğerleri özelleştirilebilir ve builder'da ayarlanabilir. |
| **didSelectProduct** | isteğe bağlı | Kullanıcı veya sistem tarafından satın almak üzere bir ürün seçildiğinde çağrılır. |
| **didStartPurchase** | isteğe bağlı | Kullanıcı satın alma sürecini başlattığında çağrılır. |
| **didFinishWebPaymentNavigation** | isteğe bağlı | Web ödeme navigasyonu tamamlandığında çağrılır. |
| **didStartRestore** | isteğe bağlı | Kullanıcı geri yükleme sürecini başlattığında çağrılır. |
| **didFailLoadingProducts** | isteğe bağlı | Ürün yükleme sırasında hata oluştuğunda çağrılır. Yeniden yüklemeyi denemek için `true` döndürün. |
| **didPartiallyLoadProducts** | isteğe bağlı | Ürünler kısmen yüklendiğinde çağrılır. |
| **showAlertItem** | isteğe bağlı | Flow veya paywallın üzerinde uyarı öğelerinin görüntülenmesini yöneten bir binding. |
| **showAlertBuilder** | isteğe bağlı | Uyarı görünümünü render etmek için kullanılan bir fonksiyon. |
| **placeholderBuilder** | isteğe bağlı | Flow veya paywall yüklenirken placeholder görünümünü render etmek için kullanılan bir fonksiyon. Varsayılan olarak `ProgressView` kullanılır. |
iOS olaylarını işleme konusundaki parametreler hakkında daha fazla bilgi için [iOS - Olayları İşleme](ios-handling-events) konusuna bakın.
### Modal olmayan görünüm olarak sunma \{#present-as-a-non-modal-view\}
Flow'ları ve paywall'ları uygulamanızın navigasyon akışında navigasyon hedefleri veya satır içi görünümler olarak da sunabilirsiniz. SwiftUI görünümlerinizde doğrudan `AdaptyFlowView` kullanın:
```swift showLineNumbers title="SwiftUI"
AdaptyFlowView(
flowConfiguration: ,
didFinishPurchase: { product, purchaseResult in
// Dismiss the view, or do nothing to let the flow continue
},
didFailPurchase: { product, error in
// Handle purchase failure
},
didFinishRestore: { profile in
// Handle successful restore
},
didFailRestore: { error in
// Handle restore failure
},
didReceiveError: { error in
// Handle the error (rendering or JS exception from the flow script).
}
)
```
## Flow'ları ve paywallları UIKit'te sunma \{#present-flows-and-paywalls-in-uikit\}
Flow'u veya paywall'ı cihaz ekranında görüntülemek için şu adımları izleyin:
1. Görüntülemek istediğiniz görsel flow'u `AdaptyUI.flowController(with:delegate:)` metodunu kullanarak başlatın:
```swift showLineNumbers title="Swift"
import AdaptyUI
let visualFlow = try AdaptyUI.flowController(
with: ,
delegate:
)
```
İstek parametreleri:
| Parametre | Zorunluluk | Açıklama |
| :----------------------- | :------- | :---------- |
| **flowConfiguration** | zorunlu | Akış veya paywallın görsel detaylarını içeren bir `AdaptyUI.FlowConfiguration` nesnesi. `AdaptyUI.getFlowConfiguration(forFlow:)` metodunu kullanın. Daha fazla bilgi için [Flow ve paywallları alma](get-pb-paywalls) konusuna bakın. |
| **delegate** | zorunlu | Flow ve paywall olaylarını dinlemek için kullanılan `AdaptyFlowControllerDelegate`. Daha fazla bilgi için [Flow & paywall olaylarını yönetme](ios-handling-events) konusuna bakın. |
Döndürür:
| Nesne | Açıklama |
| :---------------------- | :------------------------------------------------------- |
| **AdaptyFlowController** | İstenen flow veya paywall ekranını temsil eden bir nesne. |
2. Nesne başarıyla oluşturulduktan sonra cihazın ekranında görüntüleyebilirsiniz:
```swift showLineNumbers title="Swift"
present(visualFlow, animated: true)
```
:::tip
Adapty SDK'nın bir mobil uygulamaya nasıl entegre edildiğine dair gerçek bir örnek görmek ister misiniz? Tam kurulumu, paywall görüntüleme, satın alma yapma ve diğer temel işlevleri içeren [örnek uygulamalarımıza](sample-apps) göz atın.
:::
Paywall Builder ile bir paywall özelleştirdiyseniz, onu kullanıcıya göstermek için mobil uygulama kodunuzda ayrıca render etmeniz gerekmez. Böyle bir paywall, hem ne gösterileceğini hem de nasıl gösterileceğini içerir.
`AdaptyUI.PaywallConfiguration` nesnesini almak için bkz. [Paywall Builder paywalllarını ve yapılandırmalarını getirme](get-pb-paywalls).
## SwiftUI'da paywallları sunma \{#present-paywalls-in-swiftui\}
### Cihaz ekranında modal görünüm olarak sunma \{#present-as-a-modal-view\}
Görsel paywallı cihaz ekranında modal görünüm olarak göstermek için SwiftUI'da `.paywall` modifier'ını kullanın:
```swift showLineNumbers title="SwiftUI"
@State var paywallPresented = false // ensure that you manage this variable state and set it to `true` at the moment you want to show the paywall
var body: some View {
Text("Hello, AdaptyUI!")
.paywall(
isPresented: $paywallPresented,
paywallConfiguration: ,
didPerformAction: { action in
switch action {
case .close:
paywallPresented = false
default:
// Handle other actions
break
}
},
didFinishPurchase: { product, profile in paywallPresented = false },
didFailPurchase: { product, error in /* handle the error */ },
didFinishRestore: { profile in /* check access level and dismiss */ },
didFailRestore: { error in /* handle the error */ },
didFailRendering: { error in paywallPresented = false }
)
}
```
Parameters:
| Parametre | Zorunlu | Açıklama |
|:----------------------------------|:---------|:----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| **isPresented** | zorunlu | Paywall ekranının görüntülenip görüntülenmeyeceğini yöneten bir binding. |
| **paywallConfiguration** | zorunlu | Paywallın görsel ayrıntılarını içeren bir `AdaptyUI.PaywallConfiguration` nesnesi. `AdaptyUI.paywallConfiguration(for:products:viewConfiguration:observerModeResolver:tagResolver:timerResolver:)` metodunu kullanın. Daha fazla bilgi için [Paywall Builder paywalllarını ve yapılandırmalarını getirme](get-pb-paywalls) konusuna bakın. |
| **didFailPurchase** | zorunlu | `Adapty.makePurchase()` başarısız olduğunda çağrılır. |
| **didFinishRestore** | zorunlu | `Adapty.restorePurchases()` başarıyla tamamlandığında çağrılır. |
| **didFailRestore** | zorunlu | `Adapty.restorePurchases()` başarısız olduğunda çağrılır. |
| **didFailRendering** | zorunlu | Arayüz oluşturulurken bir hata meydana gelirse çağrılır. Bu durumda [Adapty Destek](mailto:support@adapty.io) ile iletişime geçin. |
| **fullScreen** | isteğe bağlı | Paywallın tam ekran modunda mı yoksa modal olarak mı görüneceğini belirler. Varsayılan değer `true`'dur. |
| **didAppear** | isteğe bağlı | Paywall görünümü sunulduğunda çağrılır. |
| **didDisappear** | isteğe bağlı | Paywall görünümü kapatıldığında çağrılır. |
| **didPerformAction** | isteğe bağlı | Kullanıcı bir düğmeye tıkladığında çağrılır. Farklı düğmelerin farklı aksiyon ID'leri vardır. `close` ve `openURL` olmak üzere iki aksiyon ID'si önceden tanımlıdır; diğerleri özeldir ve builder'da ayarlanabilir. |
| **didSelectProduct** | isteğe bağlı | Bir ürün satın almak üzere seçildiyse (kullanıcı veya sistem tarafından) bu callback çağrılır. |
| **didStartPurchase** | isteğe bağlı | Kullanıcı satın alma işlemine başladığında çağrılır. |
| **didFinishPurchase** | isteğe bağlı | `Adapty.makePurchase()` başarıyla tamamlandığında çağrılır. |
| **didFinishWebPaymentNavigation** | isteğe bağlı | Web ödeme navigasyonu tamamlandığında çağrılır. |
| **didStartRestore** | isteğe bağlı | Kullanıcı geri yükleme işlemine başladığında çağrılır. |
| **didFailLoadingProducts** | isteğe bağlı | Ürün yükleme sırasında hata oluştuğunda çağrılır. Yüklemeyi yeniden denemek için `true` döndürün. |
| **didPartiallyLoadProducts** | isteğe bağlı | Ürünler kısmen yüklendiğinde çağrılır. |
| **showAlertItem** | isteğe bağlı | Paywallın üzerindeki uyarı öğelerinin görüntülenmesini yöneten bir binding. |
| **showAlertBuilder** | isteğe bağlı | Uyarı görünümünü oluşturmaya yarayan bir fonksiyon. |
| **placeholderBuilder** | isteğe bağlı | Paywall yüklenirken yer tutucu görünümünü oluşturmaya yarayan bir fonksiyon. |
iOS olaylarını işleme hakkında parametreler için [iOS - Olayları işleme](ios-handling-events) konusuna bakın.
### Kalıcı olmayan görünüm olarak sunma \{#present-as-a-non-modal-view\}
Paywall'ları uygulamanızın navigasyon akışında bir navigasyon hedefi veya satır içi görünüm olarak da sunabilirsiniz. SwiftUI görünümlerinizde doğrudan `AdaptyPaywallView` kullanın:
```swift showLineNumbers title="SwiftUI"
AdaptyPaywallView(
paywallConfiguration: ,
didFailPurchase: { product, error in
// Handle purchase failure
},
didFinishRestore: { profile in
// Handle successful restore
},
didFailRestore: { error in
// Handle restore failure
},
didFailRendering: { error in
// Handle rendering error
}
)
```
## UIKit'te paywall'ları sunma \{#present-paywalls-in-uikit\}
Paywall'ı cihaz ekranında görüntülemek için şunları yapın:
1. Görüntülemek istediğiniz paywall'ı `.paywallController(for:products:viewConfiguration:delegate:)` metodunu kullanarak başlatın:
```swift showLineNumbers title="Swift"
import AdaptyUI
let visualPaywall = AdaptyUI.paywallController(
with: ,
delegate:
)
```
İstek parametreleri:
| Parametre | Zorunluluk | Açıklama |
| :----------------------- | :------- | :---------- |
| **paywall configuration** | zorunlu | Paywallın görsel ayrıntılarını içeren bir `AdaptyUI.PaywallConfiguration` nesnesi. `AdaptyUI.getPaywallConfiguration(forPaywall:locale:)` metodunu kullanın. Daha fazla bilgi için [Paywall Builder paywalllarını ve yapılandırmalarını getirme](get-pb-paywalls) konusuna bakın. |
| **delegate** | zorunlu | Paywall olaylarını dinlemek için bir `AdaptyPaywallControllerDelegate`. Daha fazla bilgi için [Paywall olaylarını yönetme](ios-handling-events) konusuna bakın. |
Döner:
| Nesne | Açıklama |
| :---------------------- | :--------------------------------------------------- |
| **AdaptyPaywallController** | İstenen paywall ekranını temsil eden bir nesne |
2. Nesne başarıyla oluşturulduktan sonra cihaz ekranında gösterebilirsiniz:
```swift showLineNumbers title="Swift"
present(visualPaywall, animated: true)
```
:::tip
Adapty SDK'nın bir mobil uygulamaya nasıl entegre edildiğini gerçek bir örnekle görmek ister misiniz? Kurulumun tamamını, paywall gösterimi, satın alma işlemleri ve diğer temel işlevler dahil olmak üzere ele alan [örnek uygulamalarımıza](sample-apps) göz atın.
:::
---
# File: handle-paywall-actions
---
---
title: "Flow aksiyonlarına yanıt verme - iOS"
description: "iOS uygulamanızda paywall ve onboarding flow'larındaki buton aksiyonlarını yönetin ve kullanıcı girdilerini işleyin."
---
Adapty Flow Builder veya Paywall Builder kullanarak flow veya paywall oluşturuyorsanız, butonları doğru şekilde yapılandırmanız kritik önem taşır:
1. [Paywall Builder'da bir düğme ekleyin](paywall-buttons) ve ona önceden var olan bir eylem atayın ya da özel bir eylem ID'si oluşturun.
2. Atadığınız her eylemi işlemek için uygulama kodunuzu yazın.
Bu kılavuz, özel ve önceden var olan eylemlerin kodunuzda nasıl işleneceğini gösterir.
:::warning
**Yalnızca flow/paywall kapanışları ve URL açma işlemleri otomatik olarak yönetilir.** Diğer tüm düğme eylemleri, uygulama kodunda uygun bir yanıt uygulaması gerektirir.
:::
:::note
iOS SDK, `AdaptySystemRequestsHandler` aracılığıyla bildirim izinleri veya kamera erişimi gibi sistem izin isteklerine yanıt verebilir. Flow'lar henüz bu tür istekleri tetiklemiyor, dolayısıyla şimdilik bunları ele almanıza gerek yok.
:::
## Flow ve paywallları kapatma \{#close-flows-and-paywalls\}
Flow veya paywallınıza bir kapatma düğmesi eklemek için:
1. Builder'da bir düğme ekleyin ve **Close** eylemini atayın.
2. Uygulama kodunuzda `close` eylemi için bir handler uygulayın.
:::info
iOS SDK'da `close` eylemi, flow veya paywall'ı varsayılan olarak kapatır. Ancak gerekirse bu davranışı kodunuzda geçersiz kılabilirsiniz. Örneğin, bir flow'u kapatmak başka bir flow'u açmayı tetikleyebilir.
:::
```swift
.flow(
isPresented: $flowPresented,
flowConfiguration: flowConfiguration,
didPerformAction: { action in
switch action {
case .close:
flowPresented = false // dismiss the flow or paywall
default:
break
}
},
didFinishPurchase: { product, purchaseResult in /* dismiss, or do nothing to let the flow continue */ },
didFailPurchase: { product, error in /* handle the error */ },
didFinishRestore: { profile in /* check access level and dismiss */ },
didFailRestore: { error in /* handle the error */ },
didReceiveError: { error in flowPresented = false }
)
```
## Flow ve paywall'lardan URL açma \{#open-urls-from-flows-and-paywalls\}
:::tip
Bir grup bağlantı eklemek istiyorsanız (örneğin, kullanım koşulları ve satın alma geri yükleme), builder'da bir **Link** öğesi ekleyin ve bunu **Open URL** eylemiyle düğmelerle aynı şekilde ele alın.
:::
Flow veya paywall'ınızdan bağlantı açan bir düğme eklemek için (örneğin, **Terms of use** veya **Privacy policy**):
1. Builder'da bir düğme ekleyin, **Open URL** eylemini atayın ve açmak istediğiniz URL'yi girin.
2. Uygulama kodunuzda, alınan URL'yi bir tarayıcıda açan `openURL` eylemi için bir işleyici uygulayın.
:::info
iOS SDK'da `openURL` eylemi, varsayılan olarak URL'yi açmayı tetikler. Ancak gerekirse bu davranışı kodunuzda geçersiz kılabilirsiniz.
:::
```swift
.flow(
isPresented: $flowPresented,
flowConfiguration: flowConfiguration,
didPerformAction: { action in
switch action {
case let .openURL(url):
UIApplication.shared.open(url, options: [:]) // default behavior
default:
break
}
},
didFinishPurchase: { product, purchaseResult in /* dismiss, or do nothing to let the flow continue */ },
didFailPurchase: { product, error in /* handle the error */ },
didFinishRestore: { profile in /* check access level and dismiss */ },
didFailRestore: { error in /* handle the error */ },
didReceiveError: { error in flowPresented = false }
)
```
## Özel eylemleri yönetme \{#handle-custom-actions\}
Başka eylemleri yönetecek bir düğme eklemek için:
1. Oluşturucuda bir düğme ekleyin, **Custom** eylemini atayın ve bir ID belirleyin.
2. Uygulama kodunuzda, oluşturduğunuz eylem ID'si için bir işleyici uygulayın.
Örneğin, başka bir abonelik teklifi seti ya da tek seferlik satın alma seçenekleriniz varsa, başka bir flow veya paywall açacak bir düğme ekleyebilirsiniz:
```swift
.flow(
isPresented: $flowPresented,
flowConfiguration: flowConfiguration,
didPerformAction: { action in
switch action {
case let .custom(id):
if id == "openNewPaywall" {
// Display another flow or paywall
}
default:
break
}
},
didFinishPurchase: { product, purchaseResult in /* dismiss, or do nothing to let the flow continue */ },
didFailPurchase: { product, error in /* handle the error */ },
didFinishRestore: { profile in /* check access level and dismiss */ },
didFailRestore: { error in /* handle the error */ },
didReceiveError: { error in flowPresented = false }
)
```
Adapty paywall builder kullanarak paywall oluşturuyorsanız, butonları doğru şekilde yapılandırmanız kritik önem taşır:
1. [Paywall builder'da bir buton](paywall-buttons) ekleyin ve bu butona mevcut bir eylem atayın ya da özel bir eylem ID'si oluşturun.
2. Atadığınız her eylemi uygulamanızın kodunda işleyecek kodu yazın.
Bu kılavuz, özel ve mevcut eylemleri kodunuzda nasıl ele alacağınızı gösterir.
:::warning
**Yalnızca satın almalar, geri yüklemeler, paywall kapanmaları ve URL açma işlemleri otomatik olarak yönetilir.** Diğer tüm buton eylemleri için uygulama kodunda uygun yanıt implementasyonu gereklidir.
:::
## Paywallları kapatma \{#close-paywalls\}
Paywallınızı kapatacak bir düğme eklemek için:
1. Paywall builder'da bir düğme ekleyin ve **Close** eylemini atayın.
2. Uygulama kodunuzda, paywall'ı kapatan `close` eylemi için bir işleyici uygulayın.
:::info
iOS SDK'da `close` eylemi, varsayılan olarak paywall'ı kapatmayı tetikler. Ancak gerekirse bu davranışı kodunuzda geçersiz kılabilirsiniz. Örneğin, bir paywall'ı kapatmak başka bir paywall'ın açılmasını tetikleyebilir.
:::
```swift
func paywallController(_ controller: AdaptyPaywallController,
didPerform action: AdaptyUI.Action) {
switch action {
case .close:
controller.dismiss(animated: true) // default behavior
break
}
}
```
## Paywalllardan URL açma \{#open-urls-from-paywalls\}
:::tip
Bir grup bağlantı eklemek istiyorsanız (ör. kullanım koşulları ve satın alma geri yükleme), paywall builder'da bir **Link** öğesi ekleyin ve bunu **Open URL** eylemine sahip düğmelerle aynı şekilde yönetin.
:::
Paywallınızdan bağlantı açan bir düğme eklemek için (ör. **Kullanım Koşulları** veya **Gizlilik Politikası**):
1. Paywall builder'da bir düğme ekleyin, **Open URL** eylemini atayın ve açmak istediğiniz URL'yi girin.
2. Uygulama kodunuzda, alınan URL'yi tarayıcıda açan `openUrl` eylemi için bir işleyici uygulayın.
:::info
iOS SDK'da `openUrl` eylemi, varsayılan olarak URL'yi açmayı tetikler. Ancak gerekirse bu davranışı kodunuzda geçersiz kılabilirsiniz.
:::
```swift
func paywallController(_ controller: AdaptyPaywallController,
didPerform action: AdaptyUI.Action) {
switch action {
case let .openURL(url):
UIApplication.shared.open(url, options: [:]) // default behavior
break
}
}
```
## Uygulamaya giriş yapma \{#log-into-the-app\}
Kullanıcıların uygulamanıza giriş yapmasını sağlayan bir düğme eklemek için:
1. Paywall builder'da bir düğme ekleyin ve **Login** eylemini atayın.
2. Uygulama kodunuzda, kullanıcınızı tanımlayan `login` eylemi için bir işleyici uygulayın.
```swift
func paywallController(_ controller: AdaptyPaywallController,
didPerform action: AdaptyUI.Action) {
switch action {
case .login:
// Show a login screen
let loginVC = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "LoginViewController")
controller.present(loginVC, animated: true)
}
}
```
## Özel eylemleri yönetme \{#handle-custom-actions\}
Diğer eylemleri yöneten bir düğme eklemek için:
1. Paywall builder'da bir düğme ekleyin, **Custom** eylemini atayın ve bir ID belirleyin.
2. Uygulama kodunuzda, oluşturduğunuz eylem ID'si için bir işleyici uygulayın.
Örneğin, başka bir abonelik teklifi veya tek seferlik satın alma seçeneğiniz varsa başka bir paywall görüntüleyen bir düğme ekleyebilirsiniz:
```swift
func paywallController(_ controller: AdaptyPaywallController,
didPerform action: AdaptyUI.Action) {
switch action {
case let .custom(id):
if id == "openNewPaywall" {
// Başka bir paywall göster
}
}
break
}
}
```
---
# File: ios-handling-events
---
---
title: "Flow ve paywall olaylarını yönetme - iOS"
description: "iOS uygulamanızda flow ve paywall olaylarını yönetin."
---
:::important
Bu kılavuz; satın almalar, geri yüklemeler, ürün seçimi ve paywall görüntüleme için olay yönetimini kapsar. Bunların yanı sıra buton işlemlerini de (paywall kapatma, bağlantı açma vb.) uygulamanız gerekir. Ayrıntılar için [buton eylemlerini yönetme kılavuzumuza](handle-paywall-actions) bakın.
:::
Flow'lar ve paywalllar, satın alma yapmak ve geri yüklemek için ekstra kod gerektirmez. Ancak uygulamanızın yanıt verebileceği bazı olaylar üretirler. Bu olaylar arasında düğme basışları (kapat düğmeleri, URL'ler, ürün seçimleri vb.) ve satın alma ile ilgili eylemler hakkında bildirimler bulunur. Bu olaylara nasıl yanıt vereceğinizi aşağıda öğrenin.
:::tip
Adapty SDK'nın bir mobil uygulamaya nasıl entegre edildiğine dair gerçek dünya örneği görmek ister misiniz? Paywall görüntüleme, satın alma yapma ve diğer temel işlevler dahil olmak üzere tam kurulumu sergileyen [örnek uygulamalarımıza](sample-apps) göz atın.
:::
## SwiftUI'da olayları yönetme \{#handling-events-in-swiftui\}
Mobil uygulamanızdaki flow veya paywall ekranında gerçekleşen süreçleri kontrol etmek ya da izlemek için SwiftUI'da `.flow` modifier'ını kullanın:
```swift showLineNumbers title="Swift"
@State var flowPresented = false
var body: some View {
Text("Hello, AdaptyUI!")
.flow(
isPresented: $flowPresented,
flowConfiguration: flowConfiguration,
didPerformAction: { action in
switch action {
case .close:
flowPresented = false
case let .openURL(url):
// handle opening the URL (incl. for terms and privacy)
default:
// handle other actions
}
},
didSelectProduct: { product in /* Handle the event */ },
didStartPurchase: { product in /* Handle the event */ },
didFinishPurchase: { product, purchaseResult in /* dismiss, or do nothing to let the flow continue */ },
didFailPurchase: { product, error in /* handle the error */ },
didStartRestore: { /* Handle the event */ },
didFinishRestore: { profile in /* check access level and dismiss */ },
didFailRestore: { error in /* handle the error */ },
didReceiveError: { error in
flowPresented = false
},
didFailLoadingProducts: { error in
// Return `true` to retry loading
return false
}
)
}
```
Yalnızca ihtiyacınız olan closure parametrelerini kaydedebilir, ihtiyaç duymadıklarınızı atlayabilirsiniz.
| Parametre | Zorunlu | Açıklama |
|:-----------------------|:---------|:----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| **isPresented** | zorunlu | Flow veya paywall ekranının görüntülenip görüntülenmeyeceğini yöneten bir binding. |
| **flowConfiguration** | zorunlu | Flow veya paywallın görsel ayrıntılarını içeren bir `AdaptyUI.FlowConfiguration` nesnesi. Daha fazla bilgi için [Flow ve paywall'ları al](get-pb-paywalls) bölümüne bakın. |
| **didFinishPurchase** | zorunlu | `Adapty.makePurchase()` başarıyla tamamlandığında çağrılır. Flow otomatik olarak kapanmaz — burada presentation binding'inizi `false` olarak ayarlayın ya da flow'un satın alma sonrasında devam etmesi için hiçbir şey yapmayın. |
| **didFailPurchase** | zorunlu | `Adapty.makePurchase()` başarısız olduğunda çağrılır. |
| **didFinishRestore** | zorunlu | `Adapty.restorePurchases()` başarıyla tamamlandığında çağrılır. |
| **didFailRestore** | zorunlu | `Adapty.restorePurchases()` başarısız olduğunda çağrılır. |
| **didReceiveError** | zorunlu | Flow bir render hatası veya flow betiğinden kaynaklanan bir çalışma zamanı hatasıyla karşılaştığında çağrılır (örneğin, bir JavaScript istisnası, `AdaptyUIError` kodu `4105`). Render hatası durumunda [Adapty Destek](mailto:support@adapty.io) ile iletişime geçin. |
| **placeholderBuilder** | isteğe bağlı | Flow veya paywall yüklenirken yer tutucu görünümü oluşturmak için kullanılan bir fonksiyon. Varsayılan olarak `ProgressView` kullanılır. |
| **fullScreen** | isteğe bağlı | Flow veya paywallın tam ekran modunda mı yoksa bir sheet olarak mı görüneceğini belirler. Varsayılan değer `true`'dur. |
| **didAppear** | isteğe bağlı | Flow veya paywall görünümü ekranda göründüğünde çağrılır. |
| **didDisappear** | isteğe bağlı | Flow veya paywall görünümü kapatıldığında çağrılır. |
| **didPerformAction** | isteğe bağlı | Kullanıcı bir butona tıkladığında çağrılır. İki eylem kimliği önceden tanımlıdır: `close` ve `openURL`; diğerleri özeldir ve builder'da ayarlanabilir. |
| **didSelectProduct** | isteğe bağlı | Kullanıcı veya sistem tarafından satın alma için bir ürün seçildiğinde çağrılır. |
| **didStartPurchase** | isteğe bağlı | Kullanıcı satın alma sürecini başlattığında çağrılır. |
| **didFinishWebPaymentNavigation** | isteğe bağlı | Web ödeme navigasyonu tamamlandığında çağrılır. |
| **didStartRestore** | isteğe bağlı | Kullanıcı geri yükleme sürecini başlattığında çağrılır. |
| **didFailLoadingProducts** | isteğe bağlı | Ürün yükleme sırasında hatalar oluştuğunda çağrılır. Yüklemeyi yeniden denemek için `true` döndürün. |
| **didPartiallyLoadProducts** | isteğe bağlı | Ürünler kısmen yüklendiğinde çağrılır. |
| **showAlertItem** | isteğe bağlı | Flow veya paywallın üzerinde uyarı öğelerinin görüntülenmesini yöneten bir binding. |
| **showAlertBuilder** | isteğe bağlı | Uyarı görünümünü oluşturmak için kullanılan bir fonksiyon. |
## UIKit'te olayları yönetme \{#handling-events-in-uikit\}
UIKit uygulamalarında olaylar, `AdaptyFlowControllerDelegate` protokolü aracılığıyla yönetilir. `AdaptyFlowController`'ı `AdaptyFlowControllerDelegate` ile nasıl kuracağınızı öğrenmek için [Flow ve paywallları gösterme - iOS](ios-present-paywalls) sayfasına bakın.
Protokol 13 metot tanımlar. Bunların dördünün varsayılan uygulaması yoktur ve uyum sağlarken mutlaka uygulanması gerekir: `didFinishPurchase`, `didFailPurchase`, `didFinishRestoreWith` ve `didFailRestoreWith`. Geri kalanlar varsayılan olarak işlemsiz (no-op) uygulamalarla gelir ve özel davranış istediğinizde bunları geçersiz kılabilirsiniz. Metotlar aşağıda amaca göre gruplandırılmıştır.
### Yaşam Döngüsü \{#lifecycle\}
```swift showLineNumbers title="Swift"
func flowControllerDidAppear(_ controller: AdaptyFlowController) { }
func flowControllerDidDisappear(_ controller: AdaptyFlowController) { }
```
Bu metodlar, flow veya paywall görünümü gösterildiğinde ya da kapatıldığında tetiklenir.
### Kullanıcı eylemleri \{#user-actions\}
```swift showLineNumbers title="Swift"
func flowController(
_ controller: AdaptyFlowController,
didPerform action: AdaptyUI.Action
) { }
```
`AdaptyUI.Action` durumları:
- `.close` — varsayılan davranış, controller'ı kapatır. Controller'ı ekranda tutmak veya ekstra temizlik işlemleri yapmak için bu davranışı override edebilirsiniz.
- `.openURL(url:)` — varsayılan davranış, URL'yi `UIApplication.shared.open(...)` ile açar.
- `.custom(id:)` — builder'da özel bir eylem ID'si atanmış butonlar için tetiklenir.
### Ürün seçimi \{#product-selection\}
```swift showLineNumbers title="Swift"
func flowController(
_ controller: AdaptyFlowController,
didSelectProduct product: AdaptyPaywallProduct
) { }
```
Kullanıcı veya sistem tarafından satın alma için bir ürün seçildiğinde çağrılır. Ürün, tam teklif bilgisini taşır (v4'te uygunluk otomatik olarak belirlenir — ayrı bir `AdaptyPaywallProductWithoutDeterminingOffer` türü yoktur).
### Satın alma etkinlikleri \{#purchase-events\}
```swift showLineNumbers title="Swift"
func flowController(
_ controller: AdaptyFlowController,
didStartPurchase product: AdaptyPaywallProduct
) { }
func flowController(
_ controller: AdaptyFlowController,
didFinishPurchase product: AdaptyPaywallProduct,
purchaseResult: AdaptyPurchaseResult
) {
if !purchaseResult.isPurchaseCancelled {
controller.dismiss(animated: true) // or do nothing to let the flow continue
}
}
func flowController(
_ controller: AdaptyFlowController,
didFailPurchase product: AdaptyPaywallProduct,
error: AdaptyError
) { }
```
`didFinishPurchase` ve `didFailPurchase` için varsayılan bir uygulama yoktur ve bunların implemente edilmesi zorunludur. Controller, başarılı bir satın alma işleminin ardından kendini kapatmaz — uygun olduğunda `controller.dismiss(animated:)` çağırın ya da çok ekranlı bir flow devam etsin istiyorsanız hiçbir şey yapmayın.
### Geri yükleme olayları \{#restore-events\}
```swift showLineNumbers title="Swift"
func flowControllerDidStartRestore(_ controller: AdaptyFlowController) { }
func flowController(
_ controller: AdaptyFlowController,
didFinishRestoreWith profile: AdaptyProfile
) { }
func flowController(
_ controller: AdaptyFlowController,
didFailRestoreWith error: AdaptyError
) { }
```
`didFinishRestoreWith` ve `didFailRestoreWith` için varsayılan bir uygulama bulunmaz. Controller'ı kapatmadan önce döndürülen `AdaptyProfile`'ın istediğiniz access level'ı içerip içermediğini kontrol edin.
### Flow hataları ve ürün yükleme hataları \{#flow-errors-and-product-loading-errors\}
```swift showLineNumbers title="Swift"
func flowController(
_ controller: AdaptyFlowController,
didReceiveError error: AdaptyUIError
) { }
func flowController(
_ controller: AdaptyFlowController,
didFailLoadingProductsWith error: AdaptyError
) -> Bool {
// Return `true` to retry product loading; default returns `false`.
return false
}
func flowController(
_ controller: AdaptyFlowController,
didPartiallyLoadProducts failedIds: [String]
) { }
```
`didReceiveError`, render hataları ve flow script'inden gelen çalışma zamanı hataları için tetiklenir (JavaScript istisnaları, `AdaptyUIError` kodu `4105`). Render hataları için [Adapty Destek](mailto:support@adapty.io) ile iletişime geçin. Yükleme hataları için geçici ağ sorunlarında yeniden denemek amacıyla `didFailLoadingProductsWith` fonksiyonundan `true` döndürün.
### Web ödeme navigasyonu \{#web-payment-navigation\}
```swift showLineNumbers title="Swift"
func flowController(
_ controller: AdaptyFlowController,
didFinishWebPaymentNavigation product: AdaptyPaywallProduct?,
error: AdaptyError?
) { }
```
Web ödeme navigasyonu tamamlandıktan sonra çağrılır; başarılı veya başarısız olup olmadığına bakılmaksızın.
:::important
Bu kılavuz, satın almalar, yenileme işlemleri, ürün seçimi ve paywall oluşturma için event yönetimini kapsamaktadır. Ayrıca buton işlemlerini de (paywallı kapatma, bağlantı açma vb.) uygulamanız gerekir. Ayrıntılar için [buton eylemlerini yönetme kılavuzumuza](handle-paywall-actions) bakın.
:::
Paywall Builder ile yapılandırılmış paywalllar, satın alma yapmak ve geri yüklemek için ekstra kod gerektirmez. Ancak uygulamanızın yanıt verebileceği bazı olaylar üretirler. Bu olaylar; düğme basışlarını (kapat düğmeleri, URL'ler, ürün seçimleri vb.) ve paywall üzerinde gerçekleştirilen satın alma ile ilgili işlemlere dair bildirimleri kapsar. Bu olaylara nasıl yanıt vereceğinizi aşağıda öğrenebilirsiniz.
Bu kılavuz yalnızca Adapty SDK v3.0 veya sonrasını gerektiren **yeni Paywall Builder paywallları** içindir.
:::tip
Adapty SDK'nın bir mobil uygulamaya nasıl entegre edildiğini gerçek dünyadan bir örnekle görmek ister misiniz? Tam kurulumu, paywall gösterimi, satın alma yapma ve diğer temel işlevleri içeren [örnek uygulamalarımıza](sample-apps) göz atın.
:::
## SwiftUI'da olayları yönetme \{#handling-events-in-swiftui\}
Mobil uygulamanızdaki paywall ekranında gerçekleşen süreçleri kontrol etmek veya izlemek için SwiftUI'da `.paywall` modifierını kullanın:
```swift showLineNumbers title="Swift"
@State var paywallPresented = false
var body: some View {
Text("Hello, AdaptyUI!")
.paywall(
isPresented: $paywallPresented,
paywall: paywall,
viewConfiguration: viewConfig,
didPerformAction: { action in
switch action {
case .close:
paywallPresented = false
case let .openURL(url):
// URL açmayı yönet (şartlar ve gizlilik dahil)
default:
// diğer eylemleri yönet
}
},
didSelectProduct: { /* Olayı yönet */ },
didStartPurchase: { /* Olayı yönet */ },
didFinishPurchase: { product, info in /* Olayı yönet */ },
didFailPurchase: { product, error in /* Olayı yönet */ },
didStartRestore: { /* Olayı yönet */ },
didFinishRestore: { /* Olayı yönet */ },
didFailRestore: { /* Olayı yönet */ },
didFailRendering: { error in
paywallPresented = false
},
didFailLoadingProducts: { error in
return false
}
)
}
```
Yalnızca ihtiyacınız olan closure parametrelerini kaydedebilir, ihtiyaç duymadıklarınızı atlayabilirsiniz. Bu durumda kullanılmayan closure parametreleri oluşturulmaz.
| Parametre | Zorunlu | Açıklama |
|:----------------------------------|:---------|:-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| **isPresented** | zorunlu | Paywall ekranının görüntülenip görüntülenmediğini yöneten bir bağlayıcı. |
| **paywallConfiguration** | zorunlu | Paywallın görsel ayrıntılarını içeren bir `AdaptyUI.PaywallConfiguration` nesnesi. `AdaptyUI.paywallConfiguration(for:products:viewConfiguration:observerModeResolver:tagResolver:timerResolver:)` metodunu kullanın. Daha fazla ayrıntı için [Paywall Builder paywalllarını ve yapılandırmalarını getirme](get-pb-paywalls) konusuna bakın. |
| **didFailPurchase** | zorunlu | Bir satın alma işlemi hatalar nedeniyle başarısız olduğunda çağrılır (örn. ödemeye izin verilmemesi, ağ sorunları, geçersiz ürün). Kullanıcı iptalleri veya bekleyen ödemeler için çağrılmaz. |
| **didFinishRestore** | zorunlu | Satın alma işlemi başarıyla tamamlandığında çağrılır. |
| **didFailRestore** | zorunlu | Bir satın alma işlemi geri yüklenirken hata oluştuğunda çağrılır. |
| **didFailRendering** | zorunlu | Arayüz oluşturulurken hata oluşursa çağrılır. Bu durumda [Adapty Destek ekibiyle iletişime geçin](mailto:support@adapty.io). |
| **fullScreen** | isteğe bağlı | Paywallın tam ekran modunda mı yoksa modal olarak mı görüneceğini belirler. Varsayılan değer `true`. |
| **didAppear** | isteğe bağlı | Paywall görünümü ekranda belirdiğinde çağrılır. Ayrıca kullanıcı paywall içindeki [web paywall düğmesine](web-paywall#step-2a-add-a-web-purchase-button) tıkladığında ve bir web paywall uygulama içi tarayıcıda açıldığında da çağrılır. |
| **didDisappear** | isteğe bağlı | Paywall görünümü kapatıldığında çağrılır. Ayrıca paywall'dan açılan bir [web paywall](web-paywall#step-2a-add-a-web-purchase-button) uygulama içi tarayıcıda ekrandan kaybolduğunda da çağrılır. |
| **didPerformAction** | isteğe bağlı | Kullanıcı bir düğmeye tıkladığında çağrılır. Farklı düğmelerin farklı eylem kimlikleri vardır. `close` ve `openURL` olmak üzere iki eylem kimliği önceden tanımlanmıştır; diğerleri özeldir ve builder'da ayarlanabilir. |
| **didSelectProduct** | isteğe bağlı | Bir ürün satın almak için seçildiğinde (kullanıcı veya sistem tarafından) bu callback çağrılır. |
| **didStartPurchase** | isteğe bağlı | Kullanıcı satın alma sürecini başlattığında çağrılır. |
| **didFinishPurchase** | isteğe bağlı | Satın alma işlemi başarıyla tamamlandığında çağrılır. |
| **didFinishWebPaymentNavigation** | isteğe bağlı | Satın alma için bir [web paywall](web-paywall) açılmaya çalışıldıktan sonra, başarılı olsun ya da olmasın, çağrılır. |
| **didStartRestore** | isteğe bağlı | Kullanıcı geri yükleme sürecini başlattığında çağrılır. |
| **didFailLoadingProducts** | isteğe bağlı | Ürün yükleme sırasında hatalar oluştuğunda çağrılır. Yüklemeyi yeniden denemek için `true` döndürün. |
| **didPartiallyLoadProducts** | isteğe bağlı | Ürünler kısmen yüklendiğinde çağrılır. |
| **showAlertItem** | isteğe bağlı | Paywall'ın üzerinde uyarı öğelerinin görüntülenmesini yöneten bir bağlayıcı. |
| **showAlertBuilder** | isteğe bağlı | Uyarı görünümünü oluşturmaya yarayan bir fonksiyon. |
| **placeholderBuilder** | isteğe bağlı | Paywall yüklenirken yer tutucu görünümü oluşturmaya yarayan bir fonksiyon. |
## UIKit'te olayları yönetme \{#handling-events-in-uikit\}
Mobil uygulamanızdaki paywall ekranında gerçekleşen süreçleri kontrol etmek veya izlemek için `AdaptyPaywallControllerDelegate` metodlarını uygulayın.
### Kullanıcı kaynaklı olaylar \{#user-generated-events\}
#### Ürün seçimi \{#product-selection\}
Bir kullanıcı satın alma için bir ürün seçerse bu metod çağrılır:
```swift showLineNumbers title="Swift"
func paywallController(
_ controller: AdaptyPaywallController,
didSelectProduct product: AdaptyPaywallProductWithoutDeterminingOffer
) { }
```
Olay örneği (Genişletmek için tıklayın)
```javascript
{
"product": {
"vendorProductId": "premium_monthly",
"localizedTitle": "Premium Monthly",
"localizedDescription": "Premium subscription for 1 month",
"localizedPrice": "$9.99",
"price": 9.99,
"currencyCode": "USD"
}
}
```
#### Satın alma başlatıldı \{#started-purchase\}
Bir kullanıcı satın alma sürecini başlatırsa bu metod çağrılır:
```swift showLineNumbers title="Swift"
func paywallController(_ controller: AdaptyPaywallController,
didStartPurchase product: AdaptyPaywallProduct) {
}
```
Olay örneği (Genişletmek için tıklayın)
```javascript
{
"product": {
"vendorProductId": "premium_monthly",
"localizedTitle": "Premium Monthly",
"localizedDescription": "Premium subscription for 1 month",
"localizedPrice": "$9.99",
"price": 9.99,
"currencyCode": "USD"
}
}
```
Observer modunda çağrılmaz. Ayrıntılar için [iOS - Observer modunda Paywall Builder paywalllarını gösterme](ios-present-paywall-builder-paywalls-in-observer-mode) konusuna bakın.
#### Web paywall kullanarak satın alma başlatıldı \{#started-purchase-using-a-web-paywall\}
Bir kullanıcı [web paywall](web-paywall) kullanarak satın alma sürecini başlatırsa bu metod çağrılır:
```swift showLineNumbers title="Swift"
func paywallController(
_ controller: AdaptyPaywallController,
shouldContinueWebPaymentNavigation product: AdaptyPaywallProduct
) {
}
```
Olay örneği (Genişletmek için tıklayın)
```javascript
{
"product": {
"vendorProductId": "premium_monthly",
"localizedTitle": "Premium Monthly",
"localizedDescription": "Premium subscription for 1 month",
"localizedPrice": "$9.99",
"price": 9.99,
"currencyCode": "USD"
}
}
```
#### Başarılı veya iptal edilen satın alma \{#successful-or-canceled-purchase\}
Satın alma başarılı olursa bu metod çağrılır:
```swift showLineNumbers title="Swift"
func paywallController(
_ controller: AdaptyPaywallController,
didFinishPurchase product: AdaptyPaywallProductWithoutDeterminingOffer,
purchaseResult: AdaptyPurchaseResult
) { }
}
```
Olay örnekleri (Genişletmek için tıklayın)
```javascript
// Successful purchase
{
"product": {
"vendorProductId": "premium_monthly",
"localizedTitle": "Premium Monthly",
"localizedDescription": "Premium subscription for 1 month",
"localizedPrice": "$9.99",
"price": 9.99,
"currencyCode": "USD"
},
"purchaseResult": {
"type": "success",
"profile": {
"accessLevels": {
"premium": {
"id": "premium",
"isActive": true,
"expiresAt": "2024-02-15T10:30:00Z"
}
}
}
}
}
// Cancelled purchase
{
"product": {
"vendorProductId": "premium_monthly",
"localizedTitle": "Premium Monthly",
"localizedDescription": "Premium subscription for 1 month",
"localizedPrice": "$9.99",
"price": 9.99,
"currencyCode": "USD"
},
"purchaseResult": {
"type": "cancelled"
}
}
```
Bu durumda paywall ekranını kapatmanızı öneririz.
Observer modunda çağrılmaz. Ayrıntılar için [iOS - Observer modunda Paywall Builder paywalllarını gösterme](ios-present-paywall-builder-paywalls-in-observer-mode) konusuna bakın.
#### Başarısız satın alma \{#failed-purchase\}
Bir satın alma hata nedeniyle başarısız olursa bu metod çağrılır. Bu; StoreKit hatalarını (ödeme kısıtlamaları, geçersiz ürünler, ağ hataları), işlem doğrulama hatalarını ve sistem hatalarını kapsar. Kullanıcı iptalleri, iptal edilmiş sonuçla birlikte `didFinishPurchase` metodunu tetikler; bekleyen ödemeler ise bu metodu tetiklemez.
```swift showLineNumbers title="Swift"
func paywallController(
_ controller: AdaptyPaywallController,
didFailPurchase product: AdaptyPaywallProduct,
error: AdaptyError
) { }
```
Olay örneği (Genişletmek için tıklayın)
```javascript
{
"product": {
"vendorProductId": "premium_monthly",
"localizedTitle": "Premium Monthly",
"localizedDescription": "Premium subscription for 1 month",
"localizedPrice": "$9.99",
"price": 9.99,
"currencyCode": "USD"
},
"error": {
"code": "purchase_failed",
"message": "Purchase failed due to insufficient funds",
"details": {
"underlyingError": "Insufficient funds in account"
}
}
}
```
Observer modunda çağrılmaz. Ayrıntılar için [iOS - Observer modunda Paywall Builder paywalllarını gösterme](ios-present-paywall-builder-paywalls-in-observer-mode) konusuna bakın.
#### Web paywall kullanarak başarısız satın alma \{#failed-purchase-using-a-web-paywall\}
`Adapty.openWebPaywall()` başarısız olursa bu metod çağrılır:
```swift showLineNumbers title="Swift"
func paywallController(
_ controller: AdaptyPaywallController,
didFailWebPaymentNavigation product: AdaptyPaywallProduct,
error: AdaptyError
) { }
```
Olay örneği (Genişletmek için tıklayın)
```javascript
{
"product": {
"vendorProductId": "premium_monthly",
"localizedTitle": "Premium Monthly",
"localizedDescription": "Premium subscription for 1 month",
"localizedPrice": "$9.99",
"price": 9.99,
"currencyCode": "USD"
},
"error": {
"code": "web_payment_failed",
"message": "Web payment navigation failed",
"details": {
"underlyingError": "Network connection error"
}
}
}
```
#### Başarılı geri yükleme \{#successful-restore\}
Satın alma geri yükleme başarılı olursa bu metod çağrılır:
```swift showLineNumbers title="Swift"
func paywallController(
_ controller: AdaptyPaywallController,
didFinishRestoreWith profile: AdaptyProfile
) { }
```
Olay örneği (Genişletmek için tıklayın)
```javascript
{
"profile": {
"accessLevels": {
"premium": {
"id": "premium",
"isActive": true,
"expiresAt": "2024-02-15T10:30:00Z"
}
},
"subscriptions": [
{
"vendorProductId": "premium_monthly",
"isActive": true,
"expiresAt": "2024-02-15T10:30:00Z"
}
]
}
}
```
Kullanıcının gerekli `accessLevel`'a sahip olması durumunda ekranı kapatmanızı öneririz. Nasıl kontrol edileceğini öğrenmek için [Abonelik durumu](subscription-status) konusuna bakın.
#### Başarısız geri yükleme \{#failed-restore\}
Satın alma geri yükleme başarısız olursa bu metod çağrılır:
```swift showLineNumbers title="Swift"
public func paywallController(
_ controller: AdaptyPaywallController,
didFailRestoreWith error: AdaptyError
) { }
```
Olay örneği (Genişletmek için tıklayın)
```javascript
{
"error": {
"code": "restore_failed",
"message": "Purchase restoration failed",
"details": {
"underlyingError": "No previous purchases found"
}
}
}
```
### Veri getirme ve oluşturma \{#data-fetching-and-rendering\}
#### Ürün yükleme hataları \{#product-loading-errors\}
Başlatma sırasında ürün dizisini geçmezseniz AdaptyUI gerekli nesneleri sunucudan kendisi alır. Bu işlem başarısız olursa AdaptyUI hatayı bu metodu çağırarak bildirir:
```swift showLineNumbers title="Swift"
public func paywallController(
_ controller: AdaptyPaywallController,
didFailLoadingProductsWith error: AdaptyError
) -> Bool {
return true
}
```
Olay örneği (Genişletmek için tıklayın)
```javascript
{
"error": {
"code": "products_loading_failed",
"message": "Failed to load products from the server",
"details": {
"underlyingError": "Network timeout"
}
}
}
```
`true` döndürürseniz AdaptyUI isteği 2 saniye sonra tekrarlar.
#### Oluşturma hataları \{#rendering-errors\}
Arayüz oluşturulurken bir hata meydana gelirse bu metod tarafından bildirilir:
```swift showLineNumbers title="Swift"
public func paywallController(
_ controller: AdaptyPaywallController,
didFailRenderingWith error: AdaptyError
) { }
```
Olay örneği (Genişletmek için tıklayın)
```javascript
{
"error": {
"code": "rendering_failed",
"message": "Failed to render paywall interface",
"details": {
"underlyingError": "Invalid paywall configuration"
}
}
}
```
Normal bir durumda bu tür hatalar oluşmamalıdır; eğer böyle bir hatayla karşılaşırsanız lütfen bize bildirin.
---
# File: ios-use-fallback-paywalls
---
---
title: "iOS - Yedekleri kullan"
description: "Kullanıcılar çevrimdışıyken veya Adapty sunucuları erişilebilir değilken durumları ele alın"
---
Akıcı bir kullanıcı deneyimi sürdürebilmek için flow'larınız, [paywall'larınız](paywalls) ve [onboarding'leriniz](onboardings) için [yedekler](/fallback-paywalls) ayarlamanız önemlidir. Bu önlem, kısmi veya tam internet bağlantısı kaybı durumunda uygulamanın işlevselliğini korur.
* **Uygulama Adapty sunucularına erişemiyorsa:**
Yedek flow veya paywall gösterebilir ve yerel onboarding yapılandırmasına erişebilir.
* **Uygulama internete erişemiyorsa:**
Yedek flow veya paywall gösterebilir. Onboarding'ler uzak içerik barındırdığından çalışabilmek için internet bağlantısı gerektirir.
:::important
Bu kılavuzdaki adımları izlemeden önce yedek yapılandırma dosyalarını Adapty'den [indirin](/local-fallback-paywalls).
:::
## Yapılandırma \{#configuration\}
1. Yedek JSON dosyasını proje paketinize ekleyin: XCode'da **File** menüsünü açın ve **Add Files to "YourProjectName"** seçeneğini seçin.
2. Hedef flow, paywall veya onboarding'i çekmeden **önce** `.setFallback` metodunu çağırın.
```swift showLineNumbers
do {
if let urlPath = Bundle.main.url(forResource: fileName, withExtension: "json") {
try await Adapty.setFallback(fileURL: urlPath)
}
} catch {
// handle the error
}
```
```swift showLineNumbers
if let url = Bundle.main.url(forResource: "ios_fallback", withExtension: "json") {
Adapty.setFallback(fileURL: url)
}
```
Parametreler:
| Parametre | Açıklama |
| :---------- |:----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| **fileURL** | Yedek yapılandırma dosyasının yolu. |
---
# File: localizations-and-locale-codes
---
---
title: "iOS SDK'da yerelleştirme ve yerel ayar kodlarını kullanma"
description: "iOS uygulamanızda global bir kitleye ulaşmak için uygulama yerelleştirmelerini ve yerel ayar kodlarını yönetin."
---
## Neden önemli \{#why-this-is-important\}
Yerel ayar kodlarının devreye girdiği birkaç senaryo vardır; örneğin uygulamanızın mevcut yerelleştirmesi için doğru paywallı getirmeye çalışırken bu durumla karşılaşabilirsiniz.
Yerel ayar kodları karmaşık bir yapıya sahip olduğundan ve platformdan platforma farklılık gösterebildiğinden, desteklediğimiz tüm platformlarda ortak bir iç standart kullanıyoruz. Ancak bu kodların karmaşıklığı nedeniyle, sunucumuza tam olarak ne gönderdiğinizi ve ardından ne olduğunu anlamanız son derece önemlidir; böylece her zaman beklediğiniz sonucu alırsınız.
## Adapty'de yerel ayar kodu standardı \{#locale-code-standard-at-adapty\}
Adapty, yerel ayar kodları için hafifçe değiştirilmiş bir [BCP 47 standardı](https://en.wikipedia.org/wiki/IETF_language_tag) kullanır: her kod, kısa çizgilerle ayrılmış küçük harfli alt etiketlerden oluşur. Bazı örnekler: `en` (İngilizce), `pt-br` (Portekizce (Brezilya)), `zh` (Basitleştirilmiş Çince), `zh-hant` (Geleneksel Çince).
## Yerel ayar kodu eşleştirme \{#locale-code-matching\}
Adapty, istemci taraflı SDK'dan yerel ayar koduyla bir çağrı aldığında ve bir paywallın ilgili yerelleştirmesini aramaya başladığında şu adımlar gerçekleşir:
1. Gelen yerel ayar dizesi küçük harfe dönüştürülür ve tüm alt çizgiler (`_`) kısa çizgilerle (`-`) değiştirilir.
2. Tam eşleşen yerel ayar koduna sahip yerelleştirme aranır.
3. Eşleşme bulunamazsa, ilk kısa çizgiden önceki alt dize alınır (`pt-br` için `pt`) ve eşleşen yerelleştirme aranır.
4. Yine eşleşme bulunamazsa, varsayılan `en` yerelleştirmesi döndürülür.
Bu sayede `'pt_BR'` gönderen bir iOS cihazı, `pt-BR` gönderen bir Android cihazı ve `pt-br` gönderen başka bir cihaz aynı sonucu alır.
## Yerelleştirmeleri uygulama: önerilen yöntem \{#implementing-localizations-recommended-way\}
Yerelleştirmeler konusunu araştırıyorsanız, büyük ihtimalle projenizde yerelleştirilmiş string dosyalarıyla zaten çalışıyorsunuzdur. Bu durumda, her yerelleştirme için ilgili dosyalarınızdan birine hedeflenen Adapty yerel ayar kodunu içeren bir anahtar-değer çifti eklemenizi öneririz. Ardından SDK'mızı çağırırken bu anahtarın değerini aşağıdaki gibi çıkarabilirsiniz:
```swift showLineNumbers
// 1. Modify your Localizable.strings files
/*
Localizable.strings - Spanish
*/
adapty_paywalls_locale = "es";
/*
Localizable.strings - Portuguese (Brazil)
*/
adapty_paywalls_locale = "pt-br";
// 2. Extract and use the locale code
let locale = NSLocalizedString("adapty_paywalls_locale", comment: "")
// pass locale code to AdaptyUI.getViewConfiguration or Adapty.getPaywall method
```
Bu yaklaşım sayesinde, uygulamanızın her kullanıcısı için hangi yerelleştirmenin getirileceği üzerinde tam kontrol sahibi olursunuz.
## Yerelleştirmeleri uygulama: alternatif yöntem \{#implementing-localizations-the-other-way\}
Her yerelleştirme için yerel ayar kodlarını açıkça tanımlamadan da benzer (ancak özdeş olmayan) sonuçlar elde edebilirsiniz. Bu yöntemde, platformunuzun sağladığı başka nesnelerden yerel ayar kodu çıkarırsınız:
```swift showLineNumbers
let locale = Locale.current.identifier
// pass locale code to AdaptyUI.getViewConfiguration or Adapty.getPaywall method
```
Bu yaklaşımı birkaç nedenden dolayı önermiyoruz:
1. iOS'ta tercih edilen diller ile mevcut yerel ayar aynı şey değildir. Yerelleştirmenin doğru seçilmesini istiyorsanız ya Apple'ın mantığına güvenmeniz gerekir (bu, yerelleştirilmiş string dosyalarıyla önerilen yaklaşımı kullandığınızda zaten otomatik olarak çalışır) ya da bu mantığı kendiniz yeniden oluşturmanız gerekir.
2. Adapty sunucusunun tam olarak ne alacağını öngörmek güçtür. Örneğin iOS'ta bir cihazdan `ar_OM@numbers='latn'` gibi bir yerel ayar elde edip sunucumuza göndermek mümkündür. Bu durumda aradığınız `ar-om` yerelleştirmesini değil, büyük ihtimalle beklenmedik olan `ar` yerelleştirmesini alırsınız.
Bu yaklaşımı kullanmaya karar verirseniz, ilgili tüm kullanım senaryolarını kapsadığınızdan emin olun.
---
# File: ios-troubleshoot-paywall-builder
---
---
title: "iOS SDK'da Paywall Builder Sorun Giderme"
description: "iOS SDK'da Paywall Builder Sorun Giderme"
---
Bu kılavuz, iOS SDK'da Adapty Paywall Builder ile tasarlanmış paywallları kullanırken karşılaşılan yaygın sorunları çözmenize yardımcı olur.
## Paywall yapılandırması alınamıyor \{#getting-a-paywall-configuration-fails\}
**Sorun**: `getPaywallConfiguration` metodu paywall yapılandırmasını getiremiyor.
**Neden**: Paywall, Paywall Builder'da cihazda görüntüleme için etkinleştirilmemiş.
**Çözüm**: Paywall Builder'da **Show on device** geçiş düğmesini etkinleştirin.
## Paywall görüntüleme sayısı çok yüksek \{#the-paywall-view-number-is-too-big\}
**Sorun**: Paywall görüntüleme sayısı beklenen değerin iki katını gösteriyor.
**Neden**: Kodunuzda `logShowFlow` (iOS SDK v4+) / `logShowPaywall` çağırıyor olabilirsiniz. Paywall Builder veya Flow Builder kullanıyorsanız bu yöntem görüntüleme sayısını çiftler. Bu araçlarla oluşturulan flow'lar ve paywall'lar için analitikler otomatik olarak takip edilir, dolayısıyla bu yöntemi çağırmanıza gerek yoktur.
**Çözüm**: Paywall Builder veya Flow Builder kullanıyorsanız kodunuzda `logShowFlow` (iOS SDK v4+) / `logShowPaywall` çağırmadığınızdan emin olun.
## Diğer sorunlar \{#other-issues\}
**Sorun**: Yukarıda ele alınmayan başka Paywall Builder kaynaklı sorunlar yaşıyorsunuz.
**Çözüm**: Gerekirse [geçiş kılavuzlarını](ios-sdk-migration-guides) kullanarak SDK'yı en son sürüme güncelleyin. Pek çok sorun, SDK'nın daha yeni sürümlerinde çözülmüştür.
---
# File: ios-present-paywall-builder-paywalls-in-observer-mode
---
---
title: "iOS SDK'da Observer modunda Paywall Builder paywalllarını sunun"
description: "Daha iyi içgörüler için observer modunda PB paywalllarını nasıl sunacağınızı öğrenin."
---
Paywall Builder kullanarak bir paywall özelleştirdiyseniz, bunu kullanıcıya göstermek için mobil uygulama kodunuzda ayrıca render etmeniz gerekmez. Böyle bir paywall, hem neyin gösterileceğini hem de nasıl gösterileceğini içerir.
:::warning
Bu bölüm yalnızca [Observer mode](observer-vs-full-mode) için geçerlidir. Observer mode'da çalışmıyorsanız [iOS - Present Paywall Builder paywalls](ios-present-paywalls) sayfasına bakın.
:::
Flow sunmaya başlamadan önce (Genişletmek için tıklayın)
1. Adapty'nin [App Store ile](initial_ios) ilk entegrasyonunu ayarlayın.
2. Adapty SDK'yı kurun ve yapılandırın. `observerMode` parametresini `true` olarak ayarladığınızdan emin olun. [iOS SDK kurulum kılavuzuna](sdk-installation-ios#activate-adapty-module-of-adapty-sdk) başvurun.
3. Adapty Kontrol Paneli'nde [ürünler oluşturun](create-product).
4. [Builder'larda flow'ları veya paywall'ları yapılandırın](create-paywall) ve ürünleri bunlara atayın.
5. [Placement'lar oluşturun ve flow'larınızı veya paywall'larınızı bunlara atayın](create-placement).
6. Mobil uygulama kodunuzda [flow'ları ve yapılandırmalarını alın](get-pb-paywalls).
1. `AdaptyObserverModeResolver` nesnesini uygulayın. Protokol, SDK v3 ile aynıdır — observer mode, flow ve paywall rendering arasında değişmez:
```swift showLineNumbers title="Swift"
func observerMode(didInitiatePurchase product: AdaptyPaywallProduct,
onStartPurchase: @escaping () -> Void,
onFinishPurchase: @escaping () -> Void) {
// use the product object to handle the purchase
// call onStartPurchase / onFinishPurchase to notify AdaptyUI about the purchase progress
}
func observerModeDidInitiateRestorePurchases(onStartRestore: @escaping () -> Void,
onFinishRestore: @escaping () -> Void) {
// call onStartRestore / onFinishRestore to notify AdaptyUI about the restore progress
}
```
2. Çözümleyicinizi `observerModeResolver:` parametresi olarak geçirerek bir flow yapılandırma nesnesi oluşturun:
```swift showLineNumbers title="Swift"
do {
let flowConfiguration = try await AdaptyUI.getFlowConfiguration(
forFlow: flow,
observerModeResolver:
)
} catch {
// handle the error
}
```
İstek parametreleri:
| Parametre | Zorunluluk | Açıklama |
| :----------------------- | :------- | :----------------------------------------------------------------------------------------------------------------------- |
| **forFlow** | zorunlu | `Adapty.getFlow(placementId:)` aracılığıyla elde edilen bir `AdaptyFlow` nesnesi. Bkz. [Flow ve paywall'ları alma](get-pb-paywalls). |
| **observerModeResolver** | zorunlu | Yukarıda uyguladığınız `AdaptyObserverModeResolver`. |
3. `AdaptyUI.flowController(with:delegate:)` kullanarak flow controller'ı başlatın:
```swift showLineNumbers title="Swift"
import AdaptyUI
let visualFlow = try AdaptyUI.flowController(
with: flowConfiguration,
delegate:
)
```
İstek parametreleri:
| Parametre | Varlık | Açıklama |
| :------------------------- | :------- | :----------------------------------------------------------------------------------------------------------------------------------------------- |
| **flowConfiguration** | gerekli | Flow'un görsel ayrıntılarını içeren bir `AdaptyUI.FlowConfiguration` nesnesi. Bkz. [Flow ve paywallları alma](get-pb-paywalls). |
| **delegate** | gerekli | Flow olaylarını dinlemek için bir `AdaptyFlowControllerDelegate`. Bkz. [Flow ve paywall olaylarını yönetme](ios-handling-events). |
Döndürür:
| Nesne | Açıklama |
| :------------------- | :----------------------------------------------------- |
| AdaptyFlowController | İstenen flow ekranını temsil eden bir nesne. |
4. Controller'ı gösterin:
```swift showLineNumbers title="Swift"
present(visualFlow, animated: true)
```
:::warning
[Paywallları satın alma işlemleriyle ilişkilendirmeyi](report-transactions-observer-mode) unutmayın. Aksi takdirde Adapty, satın almanın hangi paywall'dan geldiğini belirleyemez.
:::
SwiftUI'da, resolver ile flow yapılandırmasını çekin ve `.flow` modifier'ına geçirin:
```swift showLineNumbers title="SwiftUI"
@State var flowPresented = false
@State var flowConfiguration: AdaptyUI.FlowConfiguration?
var body: some View {
Text("Hello, AdaptyUI!")
.flow(
isPresented: $flowPresented,
flowConfiguration: flowConfiguration,
didPerformAction: { action in
switch action {
case .close:
flowPresented = false
default:
break
}
},
didFinishPurchase: { product, purchaseResult in /* dismiss, or do nothing to let the flow continue */ },
didFailPurchase: { product, error in /* handle the error */ },
didFinishRestore: { profile in /* check access level and dismiss */ },
didFailRestore: { error in /* handle the error */ },
didReceiveError: { error in flowPresented = false }
)
.task {
flowConfiguration = try? await AdaptyUI.getFlowConfiguration(
forFlow: flow,
observerModeResolver:
)
}
}
```
`getFlowConfiguration` üzerindeki `observerModeResolver:` parametresi, render edilen flow'un özel satın alma mantığınıza uymasını sağlar — modifier'ın kendisi de tam mod ile aynı callback'leri kullanır.
:::warning
[Satın alma işlemlerini paywall'larla ilişkilendirmeyi](report-transactions-observer-mode) unutmayın. Aksi takdirde Adapty, satın almanın kaynak paywall'ını belirleyemez.
:::
Paywall sunmaya başlamadan önce (Genişletmek için tıklayın)
1. Adapty'nin [Google Play](initial-android) ve [App Store](initial_ios) ile ilk entegrasyonunu kurun.
2. Adapty SDK'yı yükleyin ve yapılandırın. `observerMode` parametresini `true` olarak ayarladığınızdan emin olun. Framework'e özgü talimatlar için [iOS](sdk-installation-ios#activate-adapty-module-of-adapty-sdk) belgelerine bakın.
3. Adapty Kontrol Paneli'nde [ürünler oluşturun](create-product).
4. Adapty Kontrol Paneli'nde [paywall'ları yapılandırın, ürünleri bunlara atayın](create-paywall) ve Paywall Builder ile özelleştirin.
5. Adapty Kontrol Paneli'nde [placement'lar oluşturun ve paywall'larınızı bunlara atayın](create-placement).
6. Mobil uygulama kodunuzda [Paywall Builder paywall'larını ve yapılandırmalarını alın](get-pb-paywalls).
1. `AdaptyObserverModeResolver` nesnesini uygulayın:
```swift showLineNumbers title="Swift"
func observerMode(didInitiatePurchase product: AdaptyPaywallProduct,
onStartPurchase: @escaping () -> Void,
onFinishPurchase: @escaping () -> Void) {
// use the product object to handle the purchase
// use the onStartPurchase and onFinishPurchase callbacks to notify AdaptyUI about the process of the purchase
}
func observerModeDidInitiateRestorePurchases(onStartRestore: @escaping () -> Void,
onFinishRestore: @escaping () -> Void) {
// use the onStartRestore and onFinishRestore callbacks to notify AdaptyUI about the process of the restore
}
```
`observerMode(didInitiatePurchase:onStartPurchase:onFinishPurchase:)` olayı, kullanıcının bir satın alma işlemi başlattığını size bildirir. Bu geri çağırıma yanıt olarak kendi özel satın alma akışınızı tetikleyebilirsiniz.
`observerModeDidInitiateRestorePurchases(onStartRestore:onFinishRestore:)` olayı, kullanıcının bir geri yükleme işlemi başlattığını size bildirir. Bu geri çağırıma yanıt olarak kendi özel geri yükleme akışınızı tetikleyebilirsiniz.
Ayrıca, satın alma veya geri yükleme sürecini AdaptyUI'ya bildirmek için aşağıdaki callback'leri çağırmayı unutmayın. Bu, loader gösterimi gibi paywall'un düzgün çalışması için gereklidir:
| Callback | Açıklama |
| :----------------- | :------------------------------------------------------------------------------------------- |
| onStartPurchase() | Satın alma işleminin başladığını AdaptyUI'ya bildirmek için bu callback çağrılmalıdır. |
| onFinishPurchase() | Satın alma işleminin tamamlandığını AdaptyUI'ya bildirmek için bu callback çağrılmalıdır. |
| onStartRestore() | Geri yükleme işleminin başladığını AdaptyUI'ya bildirmek için bu callback çağrılmalıdır. |
| onFinishRestore() | Geri yükleme işleminin tamamlandığını AdaptyUI'ya bildirmek için bu callback çağrılmalıdır. |
2. Bir paywall yapılandırma nesnesi oluşturun:
```swift showLineNumbers title="Swift"
do {
let paywallConfiguration = try AdaptyUI.getPaywallConfiguration(
forPaywall: ,
observerModeResolver:
)
} catch {
// handle the error
}
```
İstek parametreleri:
| Parametre | Varlık | Açıklama |
| :----------------------- | :------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Paywall** | zorunlu | İstenen paywall için bir controller elde etmek amacıyla kullanılan `AdaptyPaywall` nesnesi. |
| **ObserverModeResolver** | zorunlu | Önceki adımda uyguladığınız `AdaptyObserverModeResolver` nesnesi. |
3. Görüntülemek istediğiniz görsel paywallı başlatmak için `.paywallController(for:products:viewConfiguration:delegate:)` metodunu kullanın:
```swift showLineNumbers title="Swift"
import AdaptyUI
let visualPaywall = AdaptyUI.paywallController(
with: ,
delegate:
)
```
İstek parametreleri:
| Parametre | Varlık | Açıklama |
| :----------------------- | :------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Paywall Configuration** | zorunlu | Paywallın görsel detaylarını içeren bir `AdaptyUI.PaywallConfiguration` nesnesi. `AdaptyUI.getPaywallConfiguration(forPaywall:locale:)` metodunu kullanın. Daha fazla bilgi için [Paywall Builder paywalllarını ve yapılandırmalarını getirme](get-pb-paywalls) konusuna bakın. |
| **Delegate** | zorunlu | Paywall olaylarını dinlemek için bir `AdaptyPaywallControllerDelegate`. Daha fazla bilgi için [Paywall olaylarını yönetme](ios-handling-events) konusuna bakın. |
Döndürür:
| Nesne | Açıklama |
| :---------------------- | :--------------------------------------------------- |
| AdaptyPaywallController | İstenen paywall ekranını temsil eden bir nesne |
Nesne başarıyla oluşturulduktan sonra şu şekilde görüntüleyebilirsiniz:
```swift showLineNumbers title="Swift"
present(visualPaywall, animated: true)
```
:::warning
[Satın alma işlemlerine paywallları bağlamayı](report-transactions-observer-mode) unutmayın. Aksi takdirde Adapty, satın almanın hangi paywalldan geldiğini belirleyemez.
:::
Görsel paywallı cihaz ekranında göstermek için SwiftUI'da `.paywall` modifier'ını kullanın:
```swift showLineNumbers title="SwiftUI"
@State var paywallPresented = false
var body: some View {
Text("Hello, AdaptyUI!")
.paywall(
isPresented: $paywallPresented,
paywallConfiguration: ,
didPerformAction: { action in
switch action {
case .close:
paywallPresented = false
default:
// Handle other actions
break
}
},
didFinishRestore: { profile in /* check access level and dismiss */ },
didFailRestore: { error in /* handle the error */ },
didFailRendering: { error in paywallPresented = false }
)
}
```
(empty input — nothing to translate)
| Parametre | Zorunluluk | Açıklama |
| :----------------------- | :------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Paywall Configuration** | zorunlu | Paywallın görsel ayrıntılarını içeren bir `AdaptyUI.PaywallConfiguration` nesnesi. `AdaptyUI.getPaywallConfiguration(forPaywall:locale:)` metodunu kullanın. Daha fazla bilgi için [Paywall Builder paywalllarını ve yapılandırmalarını getirme](get-pb-paywalls) konusuna bakın. |
| **Products** | isteğe bağlı | Ekranda ürünlerin gösterim zamanlamasını optimize etmek için `AdaptyPaywallProduct` nesnelerinden oluşan bir dizi sağlayın. `nil` geçilirse AdaptyUI gerekli ürünleri otomatik olarak getirir. |
| **TagResolver** | isteğe bağlı | Özel etiketler ve bunların çözümlenmiş değerlerinden oluşan bir sözlük tanımlayın. Özel etiketler paywall içeriğinde yer tutucu olarak kullanılır ve paywall içinde kişiselleştirilmiş içerik sunmak amacıyla belirli dizelerle dinamik olarak değiştirilir. Daha fazla bilgi için Paywall Builder'da Özel Etiketler konusuna bakın. |
| **ObserverModeResolver** | isteğe bağlı | Bir önceki adımda uyguladığınız `AdaptyObserverModeResolver` nesnesi |
Closure parametreleri:
| Closure parametresi | Açıklama |
| :------------------- | :----------------------------------------------------------------------------------------- |
| **didFinishRestore** | Adapty.restorePurchases() başarılı olursa bu callback çağrılır. |
| **didFailRestore** | Adapty.restorePurchases() başarısız olursa bu callback çağrılır. |
| **didFailRendering** | Arayüz oluşturma sırasında bir hata oluşursa bu callback çağrılır. |
Diğer closure parametreleri için [iOS - Olayları işleme](ios-handling-events) konusuna bakın.
:::warning
[Satın alma işlemlerini paywall'larla ilişkilendirmeyi](report-transactions-observer-mode) unutmayın. Aksi takdirde Adapty, satın almanın kaynak paywall'ını belirleyemez.
:::
Paywall'ları sunmaya başlamadan önce (Genişletmek için tıklayın)
1. Adapty'yi [Google Play](initial-android) ve [App Store](initial_ios) ile başlangıç entegrasyonunu yapın.
1. Adapty SDK'yı kurun ve yapılandırın. `observerMode` parametresini `true` olarak ayarladığınızdan emin olun. Framework'e özel talimatlarımıza bakın: [iOS](sdk-installation-ios#activate-adapty-module-of-adapty-sdk), [React Native](sdk-installation-reactnative), [Flutter](sdk-installation-flutter#activate-adapty-module-of-adapty-sdk) ve [Unity](sdk-installation-unity#activate-adapty-module-of-adapty-sdk).
2. Adapty Kontrol Paneli'nde [ürünler oluşturun](create-product).
3. Adapty Kontrol Paneli'nde [paywall'lar oluşturun, ürünleri bunlara atayın](create-paywall) ve Paywall Builder ile özelleştirin.
4. Adapty Kontrol Paneli'nde [placement'lar oluşturun ve paywall'larınızı bunlara atayın](create-placement).
5. Mobil uygulama kodunuzda [Paywall Builder paywall'larını ve yapılandırmalarını çekin](get-pb-paywalls).
1. `AdaptyObserverModeDelegate` nesnesini uygulayın:
```swift showLineNumbers title="Swift"
func paywallController(_ controller: AdaptyPaywallController,
didInitiatePurchase product: AdaptyPaywallProduct,
onStartPurchase: @escaping () -> Void,
onFinishPurchase: @escaping () -> Void) {
// use the product object to handle the purchase
// use the onStartPurchase and onFinishPurchase callbacks to notify AdaptyUI about the process of the purchase
}
```
`paywallController(_:didInitiatePurchase:onStartPurchase:onFinishPurchase:)` olayı, kullanıcının bir satın alma işlemi başlattığını size bildirir. Bu olaya yanıt olarak kendi özel satın alma akışınızı tetikleyebilirsiniz.
Ayrıca, satın alma sürecini AdaptyUI'ya bildirmek için aşağıdaki callback'leri çağırmayı unutmayın. Bu, yükleyiciyi göstermek gibi paywall'ın düzgün çalışması için gereklidir:
| Callback | Açıklama |
| :--------------- | :-------------------------------------------------------------------------------------------- |
| onStartPurchase | AdaptyUI'ya satın almanın başladığını bildirmek için bu callback çağrılmalıdır. |
| onFinishPurchase | AdaptyUI'ya satın almanın tamamlandığını bildirmek için bu callback çağrılmalıdır. |
2. Görüntülemek istediğiniz görsel paywall'u `.paywallController(for:products:viewConfiguration:delegate:observerModeDelegate:)` metodunu kullanarak başlatın:
```swift showLineNumbers title="Swift"
import AdaptyUI
let visualPaywall = AdaptyUI.paywallController(
for: ,
products: ,
viewConfiguration: ,
delegate:
observerModeDelegate:
)
```
İstek parametreleri:
| Parametre | Zorunluluk | Açıklama |
| :----------------------- | :------- | :----------------------------------------------------------- |
| **Paywall** | zorunlu | İstenen paywall için bir kontrolcü elde etmek amacıyla kullanılan `AdaptyPaywall` nesnesi. |
| **Products** | isteğe bağlı | Ürünlerin ekranda gösterilme zamanlamasını optimize etmek için bir `AdaptyPaywallProduct` nesneleri dizisi sağlayın. `nil` geçilirse, AdaptyUI gerekli ürünleri otomatik olarak çeker. |
| **ViewConfiguration** | zorunlu | Paywall'ın görsel ayrıntılarını içeren `AdaptyUI.LocalizedViewConfiguration` nesnesi. `AdaptyUI.getViewConfiguration(paywall:locale:)` metodunu kullanın. Daha fazla bilgi için [Paywall Builder paywall'larını ve yapılandırmalarını getirme](get-pb-paywalls) konusuna bakın. |
| **Delegate** | zorunlu | Paywall olaylarını dinlemek için kullanılan `AdaptyPaywallControllerDelegate`. Daha fazla bilgi için [Paywall olaylarını yönetme](ios-handling-events) konusuna bakın. |
| **ObserverModeDelegate** | zorunlu | Bir önceki adımda uyguladığınız `AdaptyObserverModeDelegate` nesnesi. |
| **TagResolver** | isteğe bağlı | Özel etiketlerin ve çözümlenmiş değerlerinin bir sözlüğünü tanımlayın. Özel etiketler, paywall içeriğinde yer tutucu görevi görür ve paywall içinde kişiselleştirilmiş içerik sunmak amacıyla belirli dizelerle dinamik olarak değiştirilir. Daha fazla bilgi için Paywall Builder'da Özel Etiketler konusuna bakın. |
Döndürür:
| Nesne | Açıklama |
| :---------------------- | :--------------------------------------------------- |
| AdaptyPaywallController | İstenen paywall ekranını temsil eden bir nesne |
Nesne başarıyla oluşturulduktan sonra şu şekilde görüntüleyebilirsiniz:
```swift showLineNumbers title="Swift"
present(visualPaywall, animated: true)
```
:::warning
[Satın alma işlemlerini paywall'lara ilişkilendirmeyi](report-transactions-observer-mode) unutmayın. Aksi takdirde Adapty, satın almanın kaynak paywall'ını belirleyemez.
:::
Görsel paywall'ı cihaz ekranında göstermek için SwiftUI'da `.paywall` modifier'ını kullanın:
```swift showLineNumbers title="SwiftUI"
@State var paywallPresented = false
var body: some View {
Text("Hello, AdaptyUI!")
.paywall(
isPresented: $paywallPresented,
paywall: ,
configuration: ,
didPerformAction: { action in
switch action {
case .close:
paywallPresented = false
default:
// Handle other actions
break
}
},
didFinishRestore: { profile in /* check access level and dismiss */ },
didFailRestore: { error in /* handle the error */ },
didFailRendering: { error in paywallPresented = false },
observerModeDidInitiatePurchase: { product, onStartPurchase, onFinishPurchase in
// use the product object to handle the purchase
// use the onStartPurchase and onFinishPurchase callbacks to notify AdaptyUI about the process of the purchase
},
)
}
```
(empty input — nothing to translate)
| Parametre | Zorunluluk | Açıklama |
| :---------------- | :------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Paywall** | zorunlu | İstediğiniz paywall için bir controller elde etmek amacıyla kullanılan `AdaptyPaywall` nesnesi. |
| **Product** | isteğe bağlı | Ürünlerin ekranda görüntülenme zamanlamasını optimize etmek için bir `AdaptyPaywallProduct` nesneleri dizisi sağlayın. `nil` geçilirse AdaptyUI, gerekli ürünleri otomatik olarak getirir. |
| **Configuration** | zorunlu | Paywallın görsel ayrıntılarını içeren bir `AdaptyUI.LocalizedViewConfiguration` nesnesi. `AdaptyUI.getViewConfiguration(paywall:locale:)` metodunu kullanın. Daha fazla ayrıntı için [Paywall Builder paywall'larını ve yapılandırmalarını getirme](get-pb-paywalls) konusuna bakın. |
| **TagResolver** | isteğe bağlı | Özel etiketlerin ve bunların çözümlenmiş değerlerinin bir sözlüğünü tanımlayın. Özel etiketler, paywall içeriğinde yer tutucu olarak kullanılır ve paywall içinde kişiselleştirilmiş içerik için belirli dizelerle dinamik olarak değiştirilir. Daha fazla ayrıntı için Paywall Builder'daki özel etiketler konusuna bakın. |
Closure parameters:
| Closure parametresi | Açıklama |
| :---------------------------------- | :----------------------------------------------------------------------------------------------- |
| **didFinishRestore** | Adapty.restorePurchases() başarılı olursa bu callback çağrılır. |
| **didFailRestore** | Adapty.restorePurchases() başarısız olursa bu callback çağrılır. |
| **didFailRendering** | Arayüz oluşturma sırasında bir hata oluşursa bu callback çağrılır. |
| **observerModeDidInitiatePurchase** | Bu callback, bir kullanıcı satın alma işlemi başlattığında çağrılır. |
Diğer closure parametreleri için [iOS - Olayları işleme](ios-handling-events) konusuna bakın.
:::warning
[Satın alma işlemlerini paywall'larla ilişkilendirmeyi](report-transactions-observer-mode) unutmayın. Aksi takdirde Adapty, satın almanın kaynağı olan paywall'ı belirleyemez.
:::
---
# File: ios-quickstart-manual
---
---
title: "iOS SDK'da özel paywall'unuzda satın almaları etkinleştirme"
description: "Uygulama içi satın almaları etkinleştirmek için Adapty SDK'yı özel iOS paywall'larınıza entegre edin."
---
Bu kılavuz, Adapty'yi özel paywall'larınıza nasıl entegre edeceğinizi açıklar. Paywall uygulaması üzerinde tam kontrolü elinizde tutarken Adapty SDK ürünleri getirir, yeni satın almaları yönetir ve önceki satın almaları geri yükler.
:::important
**Bu kılavuz, özel paywall uygulayan geliştiriciler içindir.** Satın alma işlemlerini etkinleştirmenin en kolay yolunu istiyorsanız [Adapty Flow Builder](ios-quickstart-paywalls)'ı kullanın. Flow Builder ile görsel bir no-code editörde flow'lar oluşturursunuz, Adapty tüm satın alma mantığını otomatik olarak yönetir ve uygulamanızı yeniden yayınlamadan farklı tasarımları test edebilirsiniz.
:::
## Başlamadan önce \{#before-you-start\}
### Ürünleri ayarlayın \{#set-up-products\}
Uygulama içi satın almaları etkinleştirmek için üç temel kavramı anlamanız gerekir:
- [**Ürünler**](product) – kullanıcıların satın alabileceği her şey (abonelikler, consumable'lar, süresiz erişim)
- [**Paywalllar**](paywalls) – hangi ürünlerin sunulacağını tanımlayan yapılandırmalar. Adapty'de paywalllar, ürünleri almanın tek yoludur; ancak bu tasarım sayesinde uygulama kodunuza dokunmadan ürünleri, fiyatları ve teklifleri değiştirebilirsiniz.
- [**Placement'lar**](placements) – uygulamanızda paywallları nerede ve ne zaman göstereceğiniz (örneğin `main`, `onboarding`, `settings`). Kontrol panelinde placement'lar için paywalllar ayarlarsınız, ardından kodunuzda placement ID'siyle bunları talep edersiniz. Bu yapı, A/B testleri yürütmeyi ve farklı kullanıcılara farklı paywalllar göstermeyi kolaylaştırır.
Özel bir paywall kullanıyor olsanız bile bu kavramları anladığınızdan emin olun. Temelde bunlar, uygulamanızda sattığınız ürünleri yönetme biçiminizdir.
Özel paywallınızı uygulamak için bir **paywall** oluşturmanız ve bunu bir **placement**'a eklemeniz gerekir. Bu kurulum, ürünlerinizi almanızı sağlar. Kontrol panelinde ne yapmanız gerektiğini anlamak için [buradaki](quickstart) hızlı başlangıç kılavuzunu takip edin.
### Kullanıcıları yönetin \{#manage-users\}
Kendi tarafınızda backend kimlik doğrulaması ile veya olmadan çalışabilirsiniz.
Ancak Adapty SDK, anonim ve tanımlanmış kullanıcıları farklı biçimde ele alır. Ayrıntıları anlamak ve kullanıcılarla doğru şekilde çalıştığınızdan emin olmak için [kimlik belirleme hızlı başlangıç kılavuzunu](ios-quickstart-identify) okuyun.
## Adım 1. Ürünleri alın \{#step-1-get-products\}
Özel paywall'ınız için ürünleri almak için şunları yapmanız gerekir:
1. [placement](placements) ID'sini `getFlow` metoduna geçirerek `flow` nesnesini alın.
2. Bu flow için ürünler dizisini `getPaywallProducts` metodunu kullanarak alın.
```swift
func loadPaywall() async {
do {
let flow = try await Adapty.getFlow(placementId: "YOUR_PLACEMENT_ID")
let products = try await Adapty.getPaywallProducts(flow: flow)
// Use products to build your custom paywall UI
} catch {
// Handle the error
}
}
```
```swift
func loadPaywall() {
Adapty.getFlow(placementId: "YOUR_PLACEMENT_ID") { result in
switch result {
case let .success(flow):
Adapty.getPaywallProducts(flow: flow) { result in
switch result {
case let .success(products):
// Use products to build your custom paywall UI
case let .failure(error):
// Handle the error
}
}
case let .failure(error):
// Handle the error
}
}
}
```
## Adım 2. Satın almaları kabul edin \{#step-2-accept-purchases\}
Kullanıcı özel paywallınızdaki bir ürüne dokunduğunda, seçilen ürünle birlikte `makePurchase` metodunu çağırın. Bu, satın alma akışını yönetir ve güncellenmiş profili döndürür.
```swift
func purchaseProduct(_ product: AdaptyPaywallProduct) async {
do {
let purchaseResult = try await Adapty.makePurchase(product: product)
switch purchaseResult {
case .userCancelled:
// User canceled the purchase
break
case .pending:
// Purchase is pending (e.g., awaiting parental approval)
break
case let .success(profile, transaction):
// Purchase successful, profile updated
break
}
} catch {
// Handle the error
}
}
```
```swift
func purchaseProduct(_ product: AdaptyPaywallProduct) {
Adapty.makePurchase(product: product) { result in
switch result {
case let .success(purchaseResult):
switch purchaseResult {
case .userCancelled:
// User canceled the purchase
break
case .pending:
// Purchase is pending (e.g., awaiting parental approval)
break
case let .success(profile, transaction):
// Purchase successful, profile updated
break
}
case let .failure(error):
// Handle the error
}
}
}
```
## Adım 3. Satın almaları geri yükleyin \{#step-3-restore-purchases\}
Apple, abonelik sunan tüm uygulamaların kullanıcıların satın almalarını geri yükleyebileceği bir yol sağlamasını zorunlu kılar. Satın almalar, kullanıcı Apple ID'siyle giriş yaptığında otomatik olarak geri yüklense de uygulamanızda yine de bir geri yükleme butonu eklemeniz gerekir.
Kullanıcı geri yükleme butonuna dokunduğunda `restorePurchases` metodunu çağırın. Bu, satın alma geçmişini Adapty ile senkronize eder ve güncellenmiş profili döndürür.
```swift
func restorePurchases() async {
do {
let profile = try await Adapty.restorePurchases()
// Restore successful, profile updated
} catch {
// Handle the error
}
}
```
```swift
func restorePurchases() {
Adapty.restorePurchases { result in
switch result {
case let .success(profile):
// Restore successful, profile updated
case let .failure(error):
// Handle the error
}
}
}
```
## Sonraki adımlar \{#next-steps\}
:::tip
Sorularınız mı var ya da sorunlarla mı karşılaşıyorsunuz? Sık sorulan soruların yanıtlarını bulabileceğiniz veya kendi sorularınızı sorabileceğiniz [destek forumumuza](https://adapty.featurebase.app/) göz atın. Ekibimiz ve topluluğumuz yardımcı olmak için burada!
:::
Paywallınız uygulamada gösterilmeye hazır. Paywalldan bir test satın almasını tamamlayabildiğinizden emin olmak için [satın almalarınızı sandbox modunda test edin](test-purchases-in-sandbox).
Ardından, paywallı gösterip göstermeyeceğinizi veya ücretli özelliklere erişim izni verip vermeyeceğinizi belirlemek için [kullanıcıların satın almayı tamamlayıp tamamlamadığını kontrol edin](ios-check-subscription-status).
---
# File: fetch-paywalls-and-products
---
---
title: "iOS SDK'da remote config paywallları için paywall ve ürün çekme"
description: "Kullanıcı monetizasyonunu artırmak için Adapty iOS SDK'da paywall ve ürünleri çekin."
---
Remote config ve özel paywallları uygulamanızda göstermeden önce, bunlara ait bilgileri çekmeniz gerekir. Bu konunun remote config ve özel paywalllarla ilgili olduğunu unutmayın. **Flow Builder** veya **Paywall Builder** ile özelleştirilmiş flow'ları veya paywallları çekme rehberi için [iOS](get-pb-paywalls), [Android](android-get-pb-paywalls), [React Native](react-native-get-pb-paywalls), [Flutter](flutter-get-pb-paywalls) ve [Unity](unity-get-pb-paywalls) sayfalarına bakın.
:::tip
Adapty SDK'nın bir mobil uygulamaya nasıl entegre edildiğini gerçek bir örnekle görmek ister misiniz? Tam kurulumu, paywall'ların gösterimini, satın alma işlemlerini ve diğer temel işlevleri içeren [örnek uygulamalarımıza](sample-apps) göz atın.
:::
Mobil uygulamanızda flow ve ürünleri getirmeye başlamadan önce (genişletmek için tıklayın)
1. Adapty Kontrol Paneli'nde [ürünlerinizi oluşturun](create-product).
2. Adapty Kontrol Paneli'nde [bir flow veya paywall oluşturun ve ürünleri ekleyin](create-paywall).
3. Adapty Kontrol Paneli'nde [placement'lar oluşturun ve flow ya da paywall'ınızı placement'a ekleyin](create-placement).
4. Mobil uygulamanıza [Adapty SDK'yı yükleyin](sdk-installation-ios).
## Flow bilgilerini getirme \{#fetch-flow-information\}
Adapty'de bir [ürün](product), App Store ve Google Play'den gelen ürünlerin bir kombinasyonudur. Bu çapraz platform ürünler, flow'lara ve paywall'lara entegre edilerek belirli mobil uygulama placement'larında gösterilmesini sağlar.
Ürünleri görüntülemek için `getFlow` metoduyla [placement'larınızdan](placements) birinden bir `AdaptyFlow` almanız gerekir.
:::important
**Ürün ID'lerini koda sabit olarak yazmayın.** Koda sabit olarak yazmanız gereken tek ID, placement ID'sidir. Flow'lar uzaktan yapılandırıldığından, ürün sayısı ve mevcut teklifler her an değişebilir. Uygulamanız bu değişiklikleri dinamik olarak ele almalıdır; bir flow bugün iki ürün döndürüyorsa yarın üç döndürebilir, tüm ürünleri kod değişikliği yapmadan göstermeniz gerekir.
:::
```swift showLineNumbers
do {
let flow = try await Adapty.getFlow(placementId: "YOUR_PLACEMENT_ID")
// the requested flow
} catch {
// handle the error
}
```
```swift showLineNumbers
Adapty.getFlow(placementId: "YOUR_PLACEMENT_ID") { result in
switch result {
case let .success(flow):
// the requested flow
case let .failure(error):
// handle the error
}
}
```
| Parametre | Zorunluluk | Açıklama |
|---------|--------|-----------|
| **placementId** | zorunlu | [Placement](placements) tanımlayıcısı. Adapty Kontrol Paneli'nde bir placement oluştururken belirttiğiniz değerdir. |
| **fetchPolicy** | varsayılan: `.reloadRevalidatingCacheData` |
SDK varsayılan olarak sunucudan veri yüklemeye çalışır; başarısız olursa önbelleğe alınmış veriyi döndürür. Kullanıcılarınızın her zaman en güncel verilere ulaşmasını sağladığından bu seçeneği öneriyoruz.
Ancak kullanıcılarınızın istikrarsız bir internet bağlantısıyla çalıştığını düşünüyorsanız, önbellekte veri varsa onu döndürmek için `.returnCacheDataElseLoad` kullanmayı değerlendirin. Bu senaryoda kullanıcılar en güncel verilere ulaşamayabilir; ancak internet bağlantısı ne kadar zayıf olursa olsun daha hızlı yükleme süreleri yaşarlar. Önbellek düzenli olarak güncellenir, bu nedenle ağ isteklerini azaltmak amacıyla oturum boyunca kullanmak güvenlidir.
Önbelleğin uygulama yeniden başlatıldığında silinmediğini, yalnızca uygulama kaldırıldığında veya manuel temizleme yapıldığında temizlendiğini unutmayın.
Adapty SDK, flow'ları ve paywall'ları iki katmanda saklar: yukarıda açıklanan düzenli olarak güncellenen önbellek ve [yedek paywall'lar](fallback-paywalls). Ayrıca flow'ları ve paywall'ları daha hızlı getirmek için CDN, CDN'e ulaşılamadığında ise bağımsız bir yedek sunucu kullanırız.
|
| **loadTimeout** | varsayılan: 5 sn |
Bu değer, metodun zaman aşımı süresini sınırlar. Zaman aşımına ulaşılırsa önbelleğe alınmış veri veya yerel yedek döndürülür.
Nadir durumlarda bu metodun, `loadTimeout` içinde belirtilenden biraz daha geç zaman aşımına uğrayabileceğini unutmayın; çünkü işlem arka planda farklı isteklerden oluşabilir.
|
:::note
v4'te `locale` parametresi `getFlow`'dan çıkarılarak `getFlowConfiguration`'a taşındı (yalnızca AdaptyUI ile render edilirken kullanılır). Özel paywalllar için tüm mevcut locale'ler `flow.remoteConfigs` içinde birlikte döndürülür; kullanıcının cihazıyla veya uygulamanızın ayarıyla eşleşen locale'i seçin.
:::
Ürün ID'lerini doğrudan koda yazmayın! Flow'lar uzaktan yapılandırıldığından, mevcut ürünler, ürün sayısı ve özel teklifler (ücretsiz deneme gibi) zamanla değişebilir. Kodunuzun bu senaryoları ele aldığından emin olun.
Örneğin, başlangıçta 2 ürün alıyorsanız uygulamanız bu 2 ürünü göstermelidir. Ancak daha sonra 3 ürün gelirse, herhangi bir kod değişikliği gerektirmeden uygulamanız 3 ürünü de göstermelidir. Doğrudan koda yazmanız gereken tek şey placement ID'dir.
Yanıt parametreleri:
| Parametre | Açıklama |
| :-------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Flow | Placement, tanımlayıcılar (`id`, `variationId`), ad, bir `remoteConfigs` dizisi (yapılandırılmış her locale için bir giriş) ve bir `hasViewConfiguration` bayrağı içeren `AdaptyFlow` nesnesi. Flow için ürünleri çekmek üzere `getPaywallProducts(flow:)` metodunu çağırın. |
## Ürünleri Getir \{#fetch-products\}
Flow'u aldıktan sonra, ona karşılık gelen ürün dizisini sorgulayabilirsiniz:
```swift showLineNumbers
do {
let products = try await Adapty.getPaywallProducts(flow: flow)
// the requested products array
} catch {
// handle the error
}
```
```swift showLineNumbers
Adapty.getPaywallProducts(flow: flow) { result in
switch result {
case let .success(products):
// the requested products array
case let .failure(error):
// handle the error
}
}
```
Yanıt parametreleri:
| Parametre | Açıklama |
| :-------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| Products | [`AdaptyPaywallProduct`](https://swift.adapty.io/documentation/adapty/adaptypaywallproduct) nesnelerinin listesi: ürün tanımlayıcısı, ürün adı, fiyat, para birimi, abonelik süresi ve diğer çeşitli özellikler. |
Kendi paywall tasarımınızı uygularken [`AdaptyPaywallProduct`](https://swift.adapty.io/documentation/adapty/adaptypaywallproduct) nesnesindeki bu özelliklere ihtiyaç duyacaksınız. Aşağıda en sık kullanılan özellikler açıklanmaktadır; tüm mevcut özellikler için bağlantılı belgeye bakın.
| Özellik | Açıklama |
|-------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| **Title** | Ürünün başlığını göstermek için `product.localizedTitle` kullanın. Yerelleştirmenin cihazın dilini değil, kullanıcının seçtiği mağaza ülkesini baz aldığını unutmayın. |
| **Price** | Fiyatın yerelleştirilmiş sürümünü göstermek için `product.localizedPrice` kullanın. Bu yerelleştirme cihazın yerel ayar bilgisine göre yapılır. Fiyata sayısal olarak `product.price` üzerinden de erişebilirsiniz. Değer yerel para biriminde verilir. İlgili para birimi sembolünü almak için `product.currencySymbol` kullanın. |
| **Subscription Period** | Periyodu (hafta, ay, yıl vb.) göstermek için `product.localizedSubscriptionPeriod` kullanın. Bu yerelleştirme cihazın yerel ayarına göre yapılır. Abonelik periyoduna programatik olarak erişmek için `product.subscriptionPeriod` kullanın. Buradan süreyi almak için `unit` enum'una (gün, hafta, ay, yıl veya bilinmiyor) erişebilirsiniz. `numberOfUnits` değeri, periyot birimi sayısını verir. Örneğin üç aylık bir abonelik için unit özelliğinde `.month`, numberOfUnits'te ise `3` görürsünüz. |
| **Introductory Offer** | Bir aboneliğin başlangıç teklifi içerip içermediğini göstermek için `product.subscriptionOffer` özelliğine bakın. Bu nesne aşağıdaki yararlı özellikleri içerir: • `offerType`: `introductory`, `promotional` ve `winBack` değerlerini alan bir enum. Ücretsiz denemeler ve başlangıç indirimli abonelikler `introductory` türündedir. • `price`: İndirimli fiyat, sayısal olarak. Ücretsiz denemeler için burada `0` değerini arayın. • `localizedPrice`: Kullanıcının yerel ayarına göre biçimlendirilmiş indirim fiyatı. • `localizedNumberOfPeriods`: Teklifin süresini cihazın yerel ayarıyla yerelleştirilmiş olarak açıklayan bir dize. Örneğin üç günlük deneme teklifi bu alanda `3 days` olarak görünür. • `subscriptionPeriod`: Teklif periyodunun ayrıntılarına bu özellik aracılığıyla da erişebilirsiniz; önceki bölümde açıklandığı gibi çalışır. • `localizedSubscriptionPeriod`: Kullanıcının yerel ayarına göre biçimlendirilmiş indirim abonelik periyodu. |
:::note
v4'te, `getPaywallProducts(flow:)` tarafından döndürülen tüm ürünler artık teklif uygunluk bilgisini içermektedir. v3'teki ayrı `getPaywallProductsWithoutDeterminingOffer` çağrısı kaldırılmıştır.
:::
## Varsayılan kitle flow'u ile flow getirme hızını artırın \{#speed-up-flow-fetching-with-default-audience-flow\}
Genellikle flow'lar neredeyse anında getirilir, bu yüzden bu süreci hızlandırmak için endişelenmenize gerek yoktur. Ancak çok sayıda kitle ve placement'ınız varsa ve kullanıcılarınızın internet bağlantısı zayıfsa, bir flow'un getirilmesi istediğinizden daha uzun sürebilir. Böyle durumlarda, hiçbir şey göstermek yerine sorunsuz bir kullanıcı deneyimi sağlamak için varsayılan bir flow görüntülemek isteyebilirsiniz.
Bunu çözmek için, belirtilen placement'ın **All Users** kitlesi için flow'u getiren `getFlowForDefaultAudience` metodunu kullanabilirsiniz. Ancak, önerilen yaklaşımın yukarıdaki [Flow bilgisini getirme](fetch-paywalls-and-products#fetch-flow-information) bölümünde ayrıntılı olarak açıklandığı gibi `getFlow` metoduyla flow'u getirmek olduğunu anlamak kritik önem taşır.
:::warning
Neden `getFlow` kullanmanızı öneriyoruz
`getFlowForDefaultAudience` metodunun birkaç önemli dezavantajı vardır:
- **Olası geriye dönük uyumluluk sorunları**: Farklı uygulama sürümleri (mevcut ve gelecekteki) için farklı flow'lar göstermeniz gerekiyorsa, bazı zorluklarla karşılaşabilirsiniz. Ya mevcut (eski) sürümü destekleyen flow'lar tasarlamanız ya da mevcut (eski) sürüme sahip kullanıcıların render edilemeyen flow'larla sorun yaşayabileceğini kabul etmeniz gerekecektir.
- **Hedefleme kaybı**: Tüm kullanıcılar **All Users** kitlesi için tasarlanmış aynı flow'u görür; bu da ülkelere, pazarlama attribution verisine veya kendi özel niteliklerinize dayalı kişiselleştirilmiş hedeflemeyi kaybetmeniz anlamına gelir.
Bu dezavantajları kabul edip daha hızlı flow getirme işleminden yararlanmak istiyorsanız, `getFlowForDefaultAudience` metodunu aşağıdaki şekilde kullanın. Aksi takdirde, [yukarıda](fetch-paywalls-and-products#fetch-flow-information) açıklanan `getFlow` metodunu kullanmaya devam edin.
:::
```swift showLineNumbers
do {
let flow = try await Adapty.getFlowForDefaultAudience(placementId: "YOUR_PLACEMENT_ID")
// the requested flow
} catch {
// handle the error
}
```
```swift showLineNumbers
Adapty.getFlowForDefaultAudience(placementId: "YOUR_PLACEMENT_ID") { result in
switch result {
case let .success(flow):
// istenen flow
case let .failure(error):
// hatayı işle
}
}
```
| Parametre | Zorunluluk | Açıklama |
|---------|--------|-----------|
| **placementId** | zorunlu | [Placement](placements) tanımlayıcısı. Adapty Kontrol Paneli'nde placement oluştururken belirttiğiniz değerdir. |
| **fetchPolicy** | varsayılan: `.reloadRevalidatingCacheData` |
SDK varsayılan olarak sunucudan veri yüklemeye çalışır; başarısız olursa önbelleğe alınmış veriyi döndürür. Kullanıcılarınızın her zaman en güncel veriye ulaşmasını sağladığından bu seçeneği öneriyoruz.
Ancak kullanıcılarınızın kararsız bir internet bağlantısıyla sık karşılaştığını düşünüyorsanız, önbellekte veri varsa onu döndürmek için `.returnCacheDataElseLoad` seçeneğini kullanabilirsiniz. Bu durumda kullanıcılar en güncel veriye ulaşamayabilir; ancak internet bağlantısı ne kadar kesintili olursa olsun daha hızlı yükleme süreleri yaşarlar. Önbellek düzenli olarak güncellendiğinden, ağ isteklerini azaltmak amacıyla oturum boyunca güvenle kullanılabilir.
Önbelleğin uygulama yeniden başlatıldığında korunduğunu, yalnızca uygulama kaldırılıp yeniden yüklendiğinde veya manuel temizlik yapıldığında silindiğini unutmayın.
|
Remote config ve özel paywallları göstermeden önce, bunlarla ilgili bilgileri almanız gerekir. Bu konunun remote config ve özel paywalllar ile ilgili olduğunu unutmayın. Paywall Builder ile özelleştirilmiş paywallları getirme konusunda rehberlik için [iOS](get-pb-paywalls), [Android](android-get-pb-paywalls), [React Native](react-native-get-pb-paywalls), [Flutter](flutter-get-pb-paywalls) ve [Unity](unity-get-pb-paywalls) sayfalarına bakın.
:::tip
Adapty SDK'nın bir mobil uygulamaya nasıl entegre edildiğini gerçek bir örnekle görmek ister misiniz? Tam kurulumu, paywall'ların gösterimini, satın alma işlemlerini ve diğer temel işlevleri içeren [örnek uygulamalarımıza](sample-apps) göz atın.
:::
Mobil uygulamanızda paywall ve ürün çekmeye başlamadan önce (genişletmek için tıklayın)
1. Adapty Kontrol Paneli'nde [ürünlerinizi oluşturun](create-product).
2. Adapty Kontrol Paneli'nde [bir paywall oluşturun ve ürünleri paywall'a ekleyin](create-paywall).
3. Adapty Kontrol Paneli'nde [placement'lar oluşturun ve paywall'ınızı placement'a ekleyin](create-placement).
4. Mobil uygulamanıza [Adapty SDK'yı yükleyin](sdk-installation-ios).
## Paywall bilgilerini çekme \{#fetch-paywall-information\}
Adapty'de bir [ürün](product), hem App Store hem de Google Play'den ürünlerin birleşimini temsil eder. Bu çapraz platform ürünler, belirli mobil uygulama placement'larında gösterebilmek için paywallara entegre edilir.
Ürünleri gösterebilmek için `getPaywall` metodunu kullanarak [placement](placements)'larınızdan birinden bir [Paywall](paywalls) almanız gerekir.
:::important
**Ürün ID'lerini koda gömmayın.** Koda gömmeniz gereken tek ID, placement ID'sidir. Paywalllar uzaktan yapılandırıldığından, ürün sayısı ve mevcut teklifler her an değişebilir. Uygulamanız bu değişiklikleri dinamik olarak yönetebilmeli; bugün iki ürün döndüren bir paywall yarın üç ürün döndürüyorsa, kod değişikliğine gerek kalmadan hepsini göstermelidir.
:::
```swift showLineNumbers
do {
let paywall = try await Adapty.getPaywall(placementId: "YOUR_PLACEMENT_ID")
// the requested paywall
} catch {
// handle the error
}
```
```swift showLineNumbers
Adapty.getPaywall(placementId: "YOUR_PLACEMENT_ID", locale: "en") { result in
switch result {
case let .success(paywall):
// the requested paywall
case let .failure(error):
// handle the error
}
}
```
| Parametre | Zorunluluk | Açıklama |
|---------|--------|-----------|
| **placementId** | zorunlu | [Placement](placements)'ın tanımlayıcısı. Adapty Kontrol Paneli'nde placement oluştururken belirttiğiniz değerdir. |
| **locale** |
isteğe bağlı
varsayılan: `en`
|
[Paywall yerelleştirmesinin](add-remote-config-locale) tanımlayıcısı. Bu parametre, eksi (**-**) karakteriyle ayrılmış bir veya daha fazla alt etiket içeren bir dil kodu olmalıdır. İlk alt etiket dili, ikincisi ise bölgeyi belirtir.
Örnek: `en` İngilizce anlamına gelir; `pt-br` Brezilya Portekizcesini temsil eder.
Yerel ayar kodları ve kullanım önerileri hakkında daha fazla bilgi için [Yerelleştirmeler ve yerel ayar kodları](localizations-and-locale-codes) sayfasına bakın.
SDK varsayılan olarak sunucudan veri yüklemeye çalışır; başarısız olursa önbellekteki veriyi döndürür. Kullanıcılarınızın her zaman en güncel veriye ulaşmasını sağladığından bu seçeneği öneriyoruz.
Ancak kullanıcılarınızın internet bağlantısının kararsız olduğunu düşünüyorsanız, önbellekte veri varsa onu döndürmek için `.returnCacheDataElseLoad` seçeneğini kullanabilirsiniz. Bu durumda kullanıcılar en güncel veriye her zaman ulaşamayabilir, ancak internet bağlantısından bağımsız olarak daha hızlı yükleme süreleri yaşarlar. Önbellek düzenli olarak güncellenir; bu nedenle oturum sırasında gereksiz ağ isteklerinden kaçınmak için güvenle kullanılabilir.
Önbelleğin uygulama yeniden başlatıldığında silinmediğini, yalnızca uygulama yeniden yüklendiğinde veya manuel temizlik yapıldığında temizlendiğini unutmayın.
Adapty SDK, paywallları iki katmanda depolar: yukarıda açıklanan düzenli olarak güncellenen önbellek ve [yedek paywalllar](fallback-paywalls). Paywallları daha hızlı çekmek için CDN, CDN'e ulaşılamadığı durumlarda ise bağımsız bir yedek sunucu kullanılır. Bu sistem, internet bağlantısının zayıf olduğu durumlarda bile paywalllarınızın en güncel sürümünü almanızı sağlamak için tasarlanmıştır.
|
| **loadTimeout** | varsayılan: 5 sn |
Bu değer, metodun zaman aşımı süresini sınırlar. Zaman aşımına ulaşılırsa önbelleğe alınmış veri veya yerel yedek döndürülür.
Nadir durumlarda bu metod, işlem arka planda farklı isteklerden oluşabileceğinden `loadTimeout`'ta belirtilenden biraz daha geç zaman aşımına uğrayabilir.
|
Ürün kimliklerini sabit kodlamayın! Paywall'lar uzaktan yapılandırıldığından, mevcut ürünler, ürün sayısı ve özel teklifler (ücretsiz deneme gibi) zaman içinde değişebilir. Kodunuzun bu senaryoları ele aldığından emin olun.
Örneğin, başlangıçta 2 ürün getiriyorsanız, uygulamanız o 2 ürünü göstermelidir. Ancak daha sonra 3 ürün getirirseniz, herhangi bir kod değişikliği gerektirmeksizin uygulamanız 3 ürünü de göstermelidir. Sabit kodlamanız gereken tek şey placement ID'sidir.
Yanıt parametreleri:
| Parametre | Açıklama |
| :-------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Paywall | Ürün ID'leri listesi, paywall tanımlayıcısı, remote config ve diğer çeşitli özellikler içeren bir [`AdaptyPaywall`](https://swift.adapty.io/documentation/adapty/adaptypaywall) nesnesi. |
## Ürünleri çekme \{#fetch-products\}
Paywall'ı aldıktan sonra, ona karşılık gelen ürün dizisini sorgulayabilirsiniz:
```swift showLineNumbers
do {
let products = try await Adapty.getPaywallProducts(paywall: paywall)
// the requested products array
} catch {
// handle the error
}
```
```swift showLineNumbers
Adapty.getPaywallProducts(paywall: paywall) { result in
switch result {
case let .success(products):
// istenen ürünler dizisi
case let .failure(error):
// hatayı işle
}
}
```
Yanıt parametreleri:
| Parametre | Açıklama |
| :-------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| Products | Ürün tanımlayıcısı, ürün adı, fiyat, para birimi, abonelik süresi ve diğer çeşitli özellikler içeren [`AdaptyPaywallProduct`](https://swift.adapty.io/documentation/adapty/adaptypaywallproduct) nesnelerinin listesi. |
Kendi paywall tasarımınızı uygularken, [`AdaptyPaywallProduct`](https://swift.adapty.io/documentation/adapty/adaptypaywallproduct) nesnesindeki bu özelliklere ihtiyaç duyacaksınız. Aşağıda en sık kullanılan özellikler gösterilmektedir; mevcut tüm özellikler hakkında ayrıntılı bilgi için bağlantılı belgeye bakın.
| Özellik | Açıklama |
|-------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| **Başlık** | Ürünün başlığını göstermek için `product.localizedTitle` kullanın. Yerelleştirme, cihazın yerel ayarına değil, kullanıcının seçtiği mağaza ülkesine göre yapılır. |
| **Fiyat** | Fiyatın yerelleştirilmiş halini göstermek için `product.localizedPrice` kullanın. Bu yerelleştirme, cihazın yerel ayar bilgisine göre yapılır. Fiyata sayısal olarak `product.price` üzerinden de erişebilirsiniz. Değer yerel para biriminde verilir. İlgili para birimi sembolünü almak için `product.currencySymbol` kullanın. |
| **Abonelik Dönemi** | Dönemi (örn. hafta, ay, yıl vb.) göstermek için `product.localizedSubscriptionPeriod` kullanın. Bu yerelleştirme, cihazın yerel ayarına göre yapılır. Abonelik dönemine programatik olarak erişmek için `product.subscriptionPeriod` kullanın. Buradan uzunluğu (gün, hafta, ay, yıl veya bilinmiyor) almak için `unit` enum'una erişebilirsiniz. `numberOfUnits` değeri, dönem birimlerinin sayısını verir. Örneğin üç aylık bir abonelik için `unit` özelliğinde `.month`, `numberOfUnits` özelliğinde ise `3` görürsünüz. |
| **Başlangıç Teklifi** | Bir aboneliğin başlangıç teklifi içerip içermediğini göstermek için `product.subscriptionOffer` özelliğine bakın. Bu nesne içinde aşağıdaki kullanışlı özellikler bulunur: • `offerType`: `introductory`, `promotional` ve `winBack` değerlerine sahip bir enum. Ücretsiz denemeler ve ilk indirimli abonelikler `introductory` türünde olur. • `price`: İndirimli fiyat, sayısal olarak. Ücretsiz denemeler için burada `0` değerini arayın. • `localizedPrice`: İndirimin kullanıcının yerel ayarına göre biçimlendirilmiş fiyatı. • `localizedNumberOfPeriods`: Teklifin süresini cihazın yerel ayarıyla açıklayan yerelleştirilmiş bir dize. Örneğin üç günlük bir deneme teklifi bu alanda `3 days` olarak görünür. • `subscriptionPeriod`: Alternatif olarak, teklif döneminin ayrıntılarını bu özellik aracılığıyla alabilirsiniz. Teklifler için bir önceki bölümde açıklanan şekilde çalışır. • `localizedSubscriptionPeriod`: İndirimin abonelik döneminin kullanıcının yerel ayarına göre biçimlendirilmiş hali. |
## iOS'ta başlangıç teklifi uygunluğunu kontrol etme \{#check-intro-offer-eligibility-on-ios\}
`getPaywallProducts` metodu varsayılan olarak başlangıç, promosyon ve geri kazanma teklifleri için uygunluğu kontrol eder. SDK teklif uygunluğunu belirlemeden önce ürünleri göstermeniz gerekiyorsa, bunun yerine `getPaywallProductsWithoutDeterminingOffer` metodunu kullanın.
:::note
İlk ürünleri gösterdikten sonra, ürünleri doğru teklif uygunluk bilgileriyle güncellemek için normal `getPaywallProducts` metodunu çağırmayı unutmayın.
:::
```swift showLineNumbers
do {
let products = try await Adapty.getPaywallProductsWithoutDeterminingOffer(paywall: paywall)
// the requested products array without subscriptionOffer
} catch {
// handle the error
}
```
```swift showLineNumbers
Adapty.getPaywallProductsWithoutDeterminingOffer(paywall: paywall) { result in
switch result {
case let .success(products):
// the requested products array without subscriptionOffer
case let .failure(error):
// handle the error
}
}
```
## Varsayılan kitle paywall'ı ile paywall çekmeyi hızlandırma \{#speed-up-paywall-fetching-with-default-audience-paywall\}
Paywalllar genellikle neredeyse anında çekilir, bu yüzden bu süreci hızlandırma konusunda endişelenmenize gerek yoktur. Ancak çok sayıda kitle ve paywall'ınız varsa ve kullanıcılarınızın internet bağlantısı zayıfsa, paywall çekme işlemi beklenenden daha uzun sürebilir. Böyle durumlarda hiç paywall göstermemek yerine kullanıcı deneyimini sorunsuz tutmak için varsayılan bir paywall görüntülemek isteyebilirsiniz.
Bu sorunu çözmek için **All Users** kitlesine ait belirtilen placement'ın paywall'ını çeken `getPaywallForDefaultAudience` metodunu kullanabilirsiniz. Ancak önerilen yaklaşımın, yukarıdaki [Paywall Bilgilerini Çekme](fetch-paywalls-and-products#fetch-paywall-information) bölümünde açıklandığı gibi `getPaywall` metodunu kullanmak olduğunu bilmeniz önemlidir.
:::warning
Neden `getPaywall` kullanmanızı öneriyoruz
`getPaywallForDefaultAudience` metodunun bazı önemli dezavantajları vardır:
- **Geriye dönük uyumluluk sorunları**: Farklı uygulama sürümleri için farklı paywalllar göstermeniz gerekiyorsa zorluklarla karşılaşabilirsiniz. Ya mevcut (eski) sürümü destekleyen paywalllar tasarlamanız ya da mevcut (eski) sürümdeki kullanıcıların düzgün render edilemeyen paywalllarla karşılaşabileceğini kabul etmeniz gerekir.
- **Hedefleme kaybı**: Tüm kullanıcılar **All Users** kitlesi için tasarlanmış aynı paywall'ı görür; bu da ülkeye, pazarlama attribution'ına veya kendi özel niteliklerinize dayalı kişiselleştirilmiş hedeflemeyi kaybetmeniz anlamına gelir.
Bu dezavantajları kabul ederek daha hızlı paywall çekme avantajından yararlanmak istiyorsanız `getPaywallForDefaultAudience` metodunu aşağıdaki gibi kullanabilirsiniz. Aksi hâlde [yukarıda](fetch-paywalls-and-products#fetch-paywall-information) açıklanan `getPaywall` metodunu kullanmaya devam edin.
:::
```swift showLineNumbers
do {
let paywall = try await Adapty.getPaywallForDefaultAudience("YOUR_PLACEMENT_ID")
// the requested paywall
} catch {
// handle the error
}
```
```swift showLineNumbers
Adapty.getPaywallForDefaultAudience(placementId: "YOUR_PLACEMENT_ID", locale: "en") { result in
switch result {
case let .success(paywall):
// the requested paywall
case let .failure(error):
// handle the error
}
}
```
:::note
`getPaywallForDefaultAudience` metodu iOS SDK 2.11.2 sürümünden itibaren kullanılabilir.
:::
| Parametre | Zorunluluk | Açıklama |
|---------|--------|-----------|
| **placementId** | zorunlu | [Placement](placements) tanımlayıcısı. Adapty Kontrol Paneli'nde placement oluştururken belirttiğiniz değerdir. |
| **locale** |
isteğe bağlı
varsayılan: `en`
|
[Paywall yerelleştirme](add-remote-config-locale) tanımlayıcısı. Bu parametre, eksi (**-**) karakteriyle ayrılmış bir veya daha fazla alt etiket içeren bir dil kodu olmalıdır. İlk alt etiket dili, ikincisi bölgeyi belirtir.
Örnek: `en` İngilizce, `pt-br` Brezilya Portekizcesi anlamına gelir.
Yerel ayar kodları ve kullanım önerileri hakkında daha fazla bilgi için [Yerelleştirmeler ve yerel ayar kodları](localizations-and-locale-codes) sayfasına bakın.
SDK varsayılan olarak sunucudan veri yüklemeye çalışır; başarısız olursa önbellekteki veriyi döndürür. Kullanıcılarınızın her zaman en güncel verilere ulaşmasını sağladığından bu seçeneği kullanmanızı öneririz.
Ancak kullanıcılarınızın internet bağlantısının kararsız olduğunu düşünüyorsanız, önbellekte veri varsa onu döndürmek için `.returnCacheDataElseLoad` seçeneğini kullanabilirsiniz. Bu durumda kullanıcılar en güncel veriye ulaşamayabilir, ancak internet bağlantısından bağımsız olarak daha hızlı yükleme süreleri yaşar. Önbellek düzenli olarak güncellenir, bu nedenle oturum boyunca gereksiz ağ isteklerini önlemek amacıyla güvenle kullanılabilir.
Önbellek, uygulama yeniden başlatıldığında korunur; yalnızca uygulama yeniden yüklendiğinde veya manuel temizleme yapıldığında sıfırlanır.
|
---
# File: present-remote-config-paywalls
---
---
title: "iOS SDK'da remote config ile tasarlanan paywall'u render etme"
description: "Kullanıcı deneyimini kişiselleştirmek için Adapty'de remote config paywall'larının nasıl sunulacağını keşfedin."
---
Remote config ile bir paywall özelleştirdiyseniz, bunu kullanıcılara göstermek için mobil uygulama kodunuzda render işlemini kendiniz uygulamanız gerekir. Remote config ihtiyaçlarınıza göre esneklik sunduğundan, paywall görünümünüzde nelerin yer alacağını ve nasıl görüneceğini siz belirlersiniz. Adapty, remote config'i çekmeniz için bir metot sunar; özel paywall'ınızı nasıl göstereceğiniz tamamen size kalmıştır.
[iOS'ta kullanıcının başlangıç teklifine uygun olup olmadığını kontrol etmeyi](fetch-paywalls-and-products#check-intro-offer-eligibility-on-ios) ve paywall görünümünü bu duruma göre ayarlamayı unutmayın.
## Flow remote config'ini alın ve sunun \{#get-flow-remote-config-and-present-it\}
v4'te bir flow, `remoteConfigs` dizisinde yapılandırılmış her locale için bir `AdaptyRemoteConfig` girişi taşır. Kullanıcının tercihiyle eşleşen locale'i seçin, ardından ihtiyaç duyduğunuz değerleri okuyun.
```swift showLineNumbers
do {
let flow = try await Adapty.getFlow(placementId: "YOUR_PLACEMENT_ID")
let config = flow.remoteConfigs.first(where: { $0.locale == "en" })
?? flow.remoteConfigs.first
let headerText = config?.dictionary?["header_text"] as? String
} catch {
// handle the error
}
```
```swift showLineNumbers
Adapty.getFlow(placementId: "YOUR_PLACEMENT_ID") { result in
let flow = try? result.get()
let config = flow?.remoteConfigs.first(where: { $0.locale == "en" })
?? flow?.remoteConfigs.first
let headerText = config?.dictionary?["header_text"] as? String
}
```
Bu noktada, gerekli tüm değerleri aldıktan sonra bunları görsel olarak çekici bir sayfada render etme ve bir araya getirme zamanı gelmiştir. Tasarımın farklı mobil telefon ekranlarına ve yönlendirmelerine uyum sağladığından emin olarak tüm cihazlarda sorunsuz ve kullanıcı dostu bir deneyim sunun.
:::warning
Adapty analitiğinin huni ve A/B testi bilgilerini yakalayabilmesi için aşağıda açıklandığı şekilde [paywall görüntüleme etkinliğini kaydettiğinizden](present-remote-config-paywalls#track-paywall-view-events) emin olun.
:::
Paywwall'ı görüntüledikten sonra, satın alma akışını kurmaya devam edin. Kullanıcı bir satın alma yaptığında, flow'unuzdaki ürünle birlikte `.makePurchase()` metodunu çağırmanız yeterlidir. `.makePurchase()` metodu hakkında ayrıntılar için [Satın alma yapma](making-purchases) bölümünü okuyun.
[Yedek paywall olarak adlandırılan bir yedek paywall oluşturmanızı](fallback-paywalls) öneririz. Bu yedek, internet bağlantısı olmadığında veya önbellek mevcut olmadığında kullanıcıya gösterilir ve bu durumlarda bile sorunsuz bir deneyim sağlar.
## Paywall görüntüleme olaylarını takip etme \{#track-paywall-view-events\}
Adapty, paywall'larınızın performansını ölçmenize yardımcı olur. Satın alma verilerini otomatik olarak toplasak da, paywall görüntüleme olaylarını kaydetmek sizin müdahalenizi gerektiriyor; çünkü bir müşterinin paywall'ı ne zaman gördüğünü yalnızca siz biliyorsunuz.
Paywall görüntüleme olayını kaydetmek için `.logShowFlow(flow)` metodunu çağırmanız yeterli. Bu işlem, funnel'lar ve A/B testlerindeki paywall metriklerinize yansıyacaktır.
:::important
[Flow Builder](adapty-flow-builder) veya [Paywall Builder](adapty-paywall-builder) tarafından oluşturulan flow'ları ya da paywall'ları görüntülüyorsanız `.logShowFlow(flow)` çağrısına gerek yoktur. Adapty bu durumlarda görüntülemeleri otomatik olarak takip eder.
:::
```swift showLineNumbers
try await Adapty.logShowFlow(flow)
```
İstek parametreleri:
| Parametre | Zorunluluk | Açıklama |
| :-------- | :------- |:-----------------------------------------------------------------------------------------|
| **flow** | zorunlu | `Adapty.getFlow(placementId:)` ile elde edilen bir `AdaptyFlow` nesnesi. |
Remote config kullanarak bir paywall özelleştirdiyseniz, kullanıcılara göstermek için mobil uygulamanızın kodunda render işlemini kendiniz uygulamanız gerekir. Remote config ihtiyaçlarınıza göre esneklik sunduğundan, paywallınıza nelerin dahil edileceğini ve nasıl görüneceğini siz belirlersiniz. Remote config aracılığıyla yapılandırılan özel paywallınızı göstermek için remote config'i çekmenizi sağlayan bir metot sunuyoruz.
[iOS'ta kullanıcının başlangıç teklifine uygun olup olmadığını kontrol etmeyi](fetch-paywalls-and-products#check-intro-offer-eligibility-on-ios) ve uygun olduğu durumu işlemek için paywall görünümünü ayarlamayı unutmayın.
## Paywall remote config'ini alma ve sunma \{#get-paywall-remote-config-and-present-it\}
Bir paywallın remote config'ini almak için `remoteConfig` özelliğine erişin ve gerekli değerleri çıkarın.
```swift showLineNumbers
do {
let paywall = try await Adapty.getPaywall(placementId: "YOUR_PLACEMENT_ID")
let headerText = paywall.remoteConfig?.dictionary?["header_text"] as? String
} catch {
// handle the error
}
```
```swift showLineNumbers
Adapty.getPaywall(placementId: "YOUR_PLACEMENT_ID") { result in
let paywall = try? result.get()
let headerText = paywall?.remoteConfig?.dictionary?["header_text"] as? String
}
```
Bu noktada gerekli tüm değerleri aldıktan sonra bunları görsel açıdan çekici bir sayfada render etme ve bir araya getirme zamanı gelmiş demektir. Tasarımın farklı mobil ekran boyutlarına ve yönlendirmelerine uyum sağladığından, çeşitli cihazlarda kesintisiz ve kullanıcı dostu bir deneyim sunduğundan emin olun.
:::warning
Adapty analitiğinin dönüşüm hunileri ve A/B testleri için bilgi toplayabilmesi amacıyla aşağıda açıklandığı gibi [paywall görüntüleme olayını kaydettiğinizden](present-remote-config-paywalls#track-paywall-view-events) emin olun.
:::
Paywallı göstermeyi tamamladıktan sonra satın alma akışını kurmaya devam edin. Kullanıcı bir satın alma yaptığında, paywallınızdaki ürünle birlikte `.makePurchase()` metodunu çağırmanız yeterlidir. `.makePurchase()` metodu hakkında ayrıntılı bilgi için [Satın alma yapma](making-purchases) bölümüne bakın.
Yedek paywall olarak adlandırılan [bir yedek paywall oluşturmanızı](fallback-paywalls) öneririz. Bu yedek, internet bağlantısı olmadığında veya önbellek mevcut olmadığında kullanıcıya gösterilir; böylece bu durumlarda bile sorunsuz bir deneyim sağlanır.
## Paywall görüntüleme olaylarını takip etme \{#track-paywall-view-events\}
Adapty, paywall'larınızın performansını ölçmenize yardımcı olur. Satın almalara ilişkin verileri otomatik olarak toplarken, paywall görüntülemelerini kayıt altına almak sizin müdahalenizi gerektirir; çünkü bir müşterinin paywall'ı ne zaman gördüğünü yalnızca siz bilirsiniz.
Bir paywall görüntüleme olayını kaydetmek için `.logShowPaywall(paywall)` metodunu çağırmanız yeterlidir; bu işlem, funnel'lardaki ve A/B testlerindeki paywall metriklerinize yansıyacaktır.
:::important
[Paywall Builder](adapty-paywall-builder) ile oluşturulmuş paywall'ları gösteriyorsanız `.logShowPaywall(paywall)` çağrısı yapmanıza gerek yoktur.
:::
```swift showLineNumbers
Adapty.logShowPaywall(paywall)
```
İstek parametreleri:
| Parametre | Zorunluluk | Açıklama |
| :---------- | :--------- |:--------------------------------------------------------------------------------------|
| **paywall** | zorunlu | Bir [`AdaptyPaywall`](https://swift.adapty.io/documentation/adapty/adaptypaywall) nesnesi. |
---
# File: making-purchases
---
---
title: "iOS SDK'da mobil uygulamada satın alma yapma"
description: "Adapty kullanarak uygulama içi satın alma ve abonelikleri yönetme rehberi."
---
Mobil uygulamanızda paywall'ları göstermek, kullanıcılara premium içerik veya hizmetlere erişim sunmanın temel adımlarından biridir. Ancak paywall'larınızı özelleştirmek için [Paywall Builder](adapty-paywall-builder) kullanıyorsanız, bu paywall'ları görüntülemek satın almaları desteklemek için yeterlidir.
Paywall Builder kullanmıyorsanız, satın alma işlemini tamamlamak ve istenen içeriğin kilidini açmak için `.makePurchase()` adlı ayrı bir metot kullanmanız gerekir. Bu metot, kullanıcıların paywall'larla etkileşime girmesini ve istedikleri işlemleri gerçekleştirmesini sağlar.
Paywall'ınızda kullanıcının satın almaya çalıştığı ürün için aktif bir promosyon teklifi varsa, Adapty bunu satın alma anında otomatik olarak uygular.
:::warning
Başlangıç teklifinin otomatik uygulanabilmesi için paywall'larınızın Paywall Builder ile oluşturulmuş olması gerektiğini unutmayın.
Diğer durumlarda, [iOS'ta kullanıcının başlangıç teklifine uygunluğunu doğrulamanız](fetch-paywalls-and-products#check-intro-offer-eligibility-on-ios) gerekir. Bu adımı atlamak uygulamanızın yayın sırasında reddedilmesine yol açabilir. Üstelik, başlangıç teklifine hak kazanan kullanıcıların tam fiyat ödenmesine neden olabilir.
:::
Tek bir adımı bile atlamadan [başlangıç yapılandırmasını](quickstart) tamamladığınızdan emin olun. Bu yapılmadan satın almaları doğrulayamayız.
## Satın alma yapma \{#make-purchase\}
:::note
**[Paywall Builder](adapty-paywall-builder) kullanıyor musunuz?** Satın almalar otomatik olarak işlenir—bu adımı atlayabilirsiniz.
**Adım adım rehber mi arıyorsunuz?** Tam bağlamlı uçtan uca uygulama talimatları için [hızlı başlangıç kılavuzuna](ios-implement-paywalls-manually) bakın.
:::
```swift showLineNumbers
do {
let purchaseResult = try await Adapty.makePurchase(product: product)
switch purchaseResult {
case .userCancelled:
// Handle the case where the user canceled the purchase
case .pending:
// Handle deferred purchases (e.g., the user will pay offline with cash)
case let .success(profile, transaction):
if profile.accessLevels["YOUR_ACCESS_LEVEL"]?.isActive ?? false {
// Grant access to the paid features
}
}
} catch {
// Handle the error
}
```
```swift showLineNumbers
Adapty.makePurchase(product: product) { result in
switch result {
case let .success(purchaseResult):
switch purchaseResult {
case .userCancelled:
// Handle the case where the user canceled the purchase
case .pending:
// Handle deferred purchases (e.g., the user will pay offline with cash)
case let .success(profile, transaction):
if profile.accessLevels["YOUR_ACCESS_LEVEL"]?.isActive ?? false {
// Grant access to the paid features
}
}
case let .failure(error):
// Handle the error
}
}
```
İstek parametreleri:
| Parametre | Zorunluluk | Açıklama |
| :---------- | :--------- | :----------------------------------------------------------------------------------------------- |
| **Product** | zorunlu | Paywall'dan alınan bir [`AdaptyPaywallProduct`](https://swift.adapty.io/documentation/adapty/adaptypaywallproduct) nesnesi. |
Yanıt parametreleri:
| Parametre | Açıklama |
|-----------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| **Profile** |
İstek başarılıysa yanıt bu nesneyi içerir. Bir [AdaptyProfile](https://swift.adapty.io/documentation/adapty/adaptyprofile) nesnesi, kullanıcının uygulamadaki access level'ları, abonelikleri ve abonelik dışı satın almaları hakkında kapsamlı bilgi sağlar.
Kullanıcının uygulamaya gerekli erişime sahip olup olmadığını belirlemek için access level durumunu kontrol edin.
|
:::warning
**Not:** Hâlâ Apple'ın StoreKit sürüm 2.0'ın altında ve Adapty SDK sürüm 2.9.0'ın altında bir sürüm kullanıyorsanız, bunun yerine [Apple App Store paylaşılan secret anahtarını](app-store-connection-configuration#step-5-enter-app-store-shared-secret) girmeniz gerekir. Bu yöntem Apple tarafından artık kullanımdan kaldırılmıştır.
:::
## App Store'dan uygulama içi satın almalar \{#in-app-purchases-from-the-app-store\}
Bir kullanıcı App Store'da satın alma başlattığında ve işlem uygulamanıza taşındığında iki seçeneğiniz vardır:
- **İşlemi hemen gerçekleştirin:** `shouldAddStorePayment` içinde `true` döndürün. Bu, Apple satın alma sistem ekranını hemen gösterir.
- **Ürün nesnesini sonraki işlem için saklayın:** `shouldAddStorePayment` içinde `false` döndürün, ardından saklanan ürünle `makePurchase`'i daha sonra çağırın. Bu, satın almayı tetiklemeden önce kullanıcıya özel bir şey göstermeniz gerektiğinde işe yarar.
Tam kod parçacığı şöyle:
```swift showLineNumbers title="Swift"
final class YourAdaptyDelegateImplementation: AdaptyDelegate {
nonisolated func shouldAddStorePayment(for product: AdaptyDeferredProduct) -> Bool {
// 1a.
// Return `true` to continue the transaction in your app. The Apple purchase system screen will show automatically.
// 1b.
// Store the product object and return `false` to defer or cancel the transaction.
false
}
// 2. Continue the deferred purchase later on by passing the product to `makePurchase` when the timing is appropriate
func continueDeferredPurchase() async {
let storedProduct: AdaptyDeferredProduct = // get the product object from 1b.
do {
try await Adapty.makePurchase(product: storedProduct)
} catch {
// handle the error
}
}
}
```
## iOS'ta teklif kodlarını kullanma \{#redeem-offer-codes-in-ios\}
Teklif kodları hakkında
Teklif kodları, belirli kullanıcılara indirim veya ücretsiz deneme sunmanıza olanak tanır. Otomatik uygulanan normal tekliflerin aksine, teklif kodları uygulama dışında — e-posta kampanyaları, sosyal medya veya basılı materyaller aracılığıyla — dağıtılır. Kullanıcılar bu kodları App Store'a girerek, bir kullanım URL'si aracılığıyla veya uygulama içi bir iletişim kutusu üzerinden kullanabilir.
Teklif kodlarını ayarlamak için App Store Connect'te bir abonelik açın ve **Offer Codes** bölümüne gidin. [Üç tür](https://developer.apple.com/help/app-store-connect/manage-subscriptions/set-up-subscription-offer-codes) teklif kodu oluşturabilirsiniz:
- **Free** — abonelik belirli bir süre boyunca ücretsizdir ve bir sonraki yenileme tam fiyat üzerinden gerçekleşir.
- **Pay as you go** — kullanıcı, belirli bir süre boyunca her faturalandırma döngüsünde indirimli fiyat öder; ardından abonelik tam fiyatla yenilenir.
- **Pay up front** — kullanıcı, teklif süresi boyunca tek seferlik indirimli bir fiyat öder; ardından abonelik tam fiyatla yenilenir.
Teklif kodlarını Adapty'ye eklemenize gerek yoktur. Apple, teklif süresi boyunca gerçekleşen her işlemi teklif kodu kategorisiyle etiketler. Bu etiket; ilk kullanımı ve sonraki tüm indirimli yenilemeleri kapsar. Adapty bu etiketi algılar ve her işlemi `offer_code` teklif kategorisiyle kaydeder. Teklif süresi sona erip abonelik tam fiyatla yenilendiğinde, etiket artık yer almaz. [Adapty Kontrol Paneli](controls-filters-grouping-compare-proceeds)'nde **Offer Code** teklif türüne göre analitikleri filtreleyebilirsiniz.
#### Gelir tutarsızlığı sorunlarını giderme \{#revenue-discrepancy-troubleshooting\}
Adapty'de bir teklif kodu işleminin indirimli teklif fiyatı yerine tam ürün fiyatıyla göründüğünü fark ederseniz App Store Connect'te aşağıdakileri doğrulayın:
- Teklif kodunun, kullanıcıların kodu kullanabileceği tüm bölgeler için doğru fiyatlandırma yapılandırılmış olmalıdır.
- Teklif fiyatı, kullanıcının bulunduğu ülke veya bölge için ayrıca ayarlanmış olmalıdır. Apple, işlemde bölgesel fiyatı gönderir. Teklif için belirli bir bölgeye ait fiyat yapılandırılmamışsa Apple tam ürün fiyatını gönderebilir.
Teklif kodu işlemlerini [Adapty Kontrol Paneli](controls-filters-grouping-compare-proceeds)'nde **Offer Code** teklif türü ve **Offer Discount Type** filtreleri aracılığıyla filtreleyip doğrulayabilirsiniz.
#### Eski promosyon kodları (kullanımdan kaldırıldı) \{#legacy-promo-codes-deprecated\}
:::warning
Apple, uygulama içi satın almalar için promosyon kodlarını Mart 2026'da kullanımdan kaldırdı. Teklif kodları, daha fazla özellikle bunların yerini alıyor: yapılandırılabilir uygunluk kriterleri, son kullanma tarihleri ve üç ayda 1 milyona kadar kod. Uygulama içi satın almalar için daha önce promosyon kodu kullandıysanız App Store Connect'te teklif kodlarına geçiş yapın.
:::
Eski promosyon kodları (uygulama başına sürüm başına en fazla 100 adet) bir aboneliğe ücretsiz erişim sağlıyordu. Teklif kodlarının aksine, Apple promosyon kodu işlemlerine indirim bilgisi eklemiyordu — makbuza tam ürün fiyatını gönderiyordu. Bunun sonucunda Adapty bu işlemleri tam fiyat üzerinden kaydediyordu ve bu durum Adapty analitikleri ile App Store Connect arasında gelir tutarsızlıklarına yol açıyordu.
Ücretsiz olması gereken ancak tam fiyatla görünen geçmişe ait işlemler görüyorsanız bunlar büyük olasılıkla eski promosyon kodlarından kaynaklanmaktadır. Bu kodlar artık kullanımdan kaldırıldığından, doğru gelir takibi için teklif kodlarına geçiş yapın.
Uygulamanızda kod kullanım sayfasını göstermek için:
```swift showLineNumbers
Adapty.presentCodeRedemptionSheet()
```
:::danger
Gözlemlerimize göre bazı uygulamalarda Teklif Kodu Kullanım sayfası güvenilir şekilde çalışmayabilir. Kullanıcıyı doğrudan App Store'a yönlendirmenizi öneririz.
Bunu yapmak için şu formattaki URL'yi açmanız gerekir:
`https://apps.apple.com/redeem?ctx=offercodes&id={apple_app_id}&code={code}`
:::
---
# File: restore-purchase
---
---
title: "iOS SDK'da mobil uygulamada satın almaları geri yükleme"
description: "Kesintisiz kullanıcı deneyimi sağlamak için Adapty'de satın almaları nasıl geri yükleyeceğinizi öğrenin."
---
Satın Almaları Geri Yükleme, kullanıcıların daha önce satın aldıkları içeriklere (abonelikler veya uygulama içi satın almalar gibi) tekrar ücret ödemeden yeniden erişmesini sağlayan bir özelliktir. Bu özellik, özellikle uygulamayı kaldırıp yeniden yükleyen ya da yeni bir cihaza geçen ve daha önce satın aldıkları içeriklere tekrar erişmek isteyen kullanıcılar için oldukça faydalıdır.
:::note
[Paywall Builder](adapty-paywall-builder) ile oluşturulan paywall'larda satın almalar, sizin tarafınızdan herhangi bir ek kod yazılmadan otomatik olarak geri yüklenir. Bu sizin durumunuzsa bu adımı atlayabilirsiniz.
:::
Paywall'ı özelleştirmek için [Paywall Builder](adapty-paywall-builder) kullanmıyorsanız satın almayı geri yüklemek için `.restorePurchases()` metodunu çağırın:
```swift showLineNumbers
do {
let profile = try await Adapty.restorePurchases()
if profile.accessLevels["YOUR_ACCESS_LEVEL"]?.isActive ?? false {
// successful access restore
}
} catch {
// handle the error
}
```
```swift showLineNumbers
Adapty.restorePurchases { [weak self] result in
switch result {
case let .success(profile):
if profile.accessLevels["YOUR_ACCESS_LEVEL"]?.isActive ?? false {
// successful access restore
}
case let .failure(error):
// handle the error
}
}
```
Yanıt parametreleri:
| Parametre | Açıklama |
|---------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| **Profile** |
Bir [`AdaptyProfile`](https://swift.adapty.io/documentation/adapty/adaptyprofile) nesnesi. Bu model, access level'lar, abonelikler ve abonelik dışı satın almalar hakkında bilgi içerir.
Kullanıcının uygulamaya erişimi olup olmadığını belirlemek için **access level** durumunu kontrol edin.
|
:::tip
Adapty SDK'nın bir mobil uygulamaya nasıl entegre edildiğini gerçek bir örnekle görmek ister misiniz? Tam kurulumu, paywall'ların gösterimini, satın alma işlemlerini ve diğer temel işlevleri içeren [örnek uygulamalarımıza](sample-apps) göz atın.
:::
---
# File: ios-transaction-management
---
---
title: "iOS SDK'da gelişmiş işlem yönetimi"
description: "Adapty SDK ile iOS uygulamanızda işlemleri manuel olarak tamamlayın."
---
:::note
Gelişmiş işlem yönetimi, Adapty iOS SDK'nın 3.12 sürümünden itibaren desteklenmektedir.
:::
Adapty'deki gelişmiş işlem yönetimi, işlemlerin nasıl ele alındığı, doğrulandığı ve tamamlandığı üzerinde size daha fazla kontrol sağlar.
Gelişmiş işlem yönetimi, birlikte çalışan üç isteğe bağlı özellik sunar:
| Özellik | Amaç |
|-------------------------------------------------------------|----------|
| [`appAccountToken`](#assign-appaccounttoken) | Apple işlemlerini dahili kullanıcı kimliğinize bağlar |
| [`jwsTransaction`](#access-the-jws-representation) | Doğrulama için Apple'ın imzalanmış işlem yükünü sağlar |
| [Manuel tamamlama](#control-transaction-finishing-behavior) | İşlemleri yalnızca backend'iniz başarıyı onayladıktan sonra tamamlamanıza olanak tanır |
Bu araçlar birlikte, Adapty işlemleri kendi backend'iyle senkronize etmeye devam ederken sağlam özel doğrulama akışları oluşturmanıza imkân verir.
:::important
Çoğu uygulamanın buna ihtiyacı yoktur.
Varsayılan olarak Adapty, StoreKit işlemlerini otomatik olarak doğrular ve tamamlar.
Bu kılavuzu yalnızca kendi backend doğrulamanızı çalıştırıyorsanız veya satın alma yaşam döngüsünü tamamen kontrol etmek istiyorsanız kullanın.
:::
## `appAccountToken` atama \{#assign-appaccounttoken\}
[`appAccountToken`](https://developer.apple.com/documentation/storekit/product/purchaseoption/appaccounttoken(_:)), App Store işlemlerini dahili kullanıcı kimliğinize bağlamanızı sağlayan bir **UUID**'dir.
StoreKit bu token'ı her işlemle ilişkilendirir; böylece backend'iniz App Store verilerini kullanıcılarınızla eşleştirebilir.
Kullanıcı başına oluşturulan kararlı bir UUID kullanın ve aynı hesap için farklı cihazlarda da bu UUID'yi yeniden kullanın.
Bu, satın almaların ve App Store bildirimlerinin doğru şekilde eşleştirilmesini sağlar.
Token'ı iki farklı şekilde ayarlayabilirsiniz: SDK etkinleştirmesi sırasında veya kullanıcıyı tanımlarken.
:::important
`appAccountToken`'ı her zaman `customerUserId` ile birlikte geçirmeniz gerekir.
Yalnızca token'ı geçerseniz işleme dahil edilmez.
:::
```swift showLineNumbers
// During configuration:
let configurationBuilder =
AdaptyConfiguration
.builder(withAPIKey: "PUBLIC_SDK_KEY")
.with(customerUserId: "YOUR_USER_ID", withAppAccountToken: UUID())
do {
try await Adapty.activate(with: configurationBuilder.build())
} catch {
// handle the error
}
// Or when identifying a user:
do {
try await Adapty.identify("YOUR_USER_ID", withAppAccountToken: UUID())
} catch {
// handle the error
}
```
```swift showLineNumbers
// During configuration:
let configurationBuilder =
AdaptyConfiguration
.builder(withAPIKey: "PUBLIC_SDK_KEY")
.with(customerUserId: "YOUR_USER_ID", withAppAccountToken: )
Adapty.activate(with: configurationBuilder.build()) { error in
// handle the error
}
// Or when identifying a user:
Adapty.identify("YOUR_USER_ID", withAppAccountToken: ) { error in
if let error {
// handle the error
}
}
```
## JWS gösterimine erişme \{#access-the-jws-representation\}
Bir satın alma yaptığınızda, sonuç Apple'ın işlemini [JWS Compact Serialization formatında](https://developer.apple.com/documentation/storekit/verificationresult/jwsrepresentation-21vgo) içerir.
Bu değeri bağımsız doğrulama veya kayıt amacıyla backend'inize iletebilirsiniz.
```swift
let result = try await Adapty.makePurchase(product: paywallProduct)
let jwsRepresentation = result.jwsTransaction
```
## İşlem tamamlama davranışını kontrol etme \{#control-transaction-finishing-behavior\}
Varsayılan olarak Adapty, StoreKit işlemlerini doğrulamanın ardından otomatik olarak tamamlar.
Backend'inizin başarıyı onaylamasına kadar tamamlamayı ertelemek istiyorsanız tamamlama davranışını manuel olarak ayarlayın.
Bu modda:
- Adapty yine de satın almaları doğrular ve kendi backend'iyle senkronize eder.
- `finish()` metodunu açıkça çağırana kadar işlemler tamamlanmamış olarak kalır.
```swift
var configBuilder = AdaptyConfiguration
.builder(withAPIKey: "YOUR_API_KEY")
.with(transactionFinishBehavior: .manual)
try await Adapty.activate(with: configBuilder.build())
```
Manuel işlem tamamlamayı kullanırken, tamamlanmamış işlemleri yönetmek için `onUnfinishedTransaction` delegate metodunu uygulamanız gerekir:
```swift showLineNumbers title="Swift"
extension YourApp: AdaptyDelegate {
func onUnfinishedTransaction(_ transaction: AdaptyUnfinishedTransaction) async {
// Perform your custom validation logic here
// When ready, finish the transaction
await transaction.finish()
}
}
```
Mevcut tüm tamamlanmamış işlemleri almak için `getUnfinishedTransactions()` metodunu kullanın:
```swift
let unfinishedTransactions = try await Adapty.getUnfinishedTransactions()
```
---
# File: implement-observer-mode
---
---
title: "iOS SDK'da Observer modu uygulama"
description: "iOS SDK'da kullanıcı abonelik olaylarını takip etmek için Adapty'de observer modunu uygulayın."
---
Kendi satın alma altyapınız varsa ve henüz tamamen Adapty'ye geçmeye hazır değilseniz, [Observer modu](observer-vs-full-mode)'nu inceleyebilirsiniz. Temel haliyle Observer Modu, gelişmiş analitik ile attribution ve analitik sistemleriyle sorunsuz entegrasyon sunar.
Bu sizin ihtiyaçlarınızı karşılıyorsa yalnızca şunları yapmanız gerekir:
1. Adapty SDK'yı yapılandırırken `observerMode` parametresini `true` olarak ayarlayarak Observer modunu etkinleştirin.
2. Mevcut satın alma altyapınızdaki işlemleri Adapty'ye [bildirin](report-transactions-observer-mode).
Paywall'lar ve A/B testi de kullanmak istiyorsanız, aşağıda açıklandığı gibi ek kurulum adımları gereklidir.
## Observer modu kurulumu \{#observer-mode-setup\}
Satın alma işlemlerini ve abonelik durumunu kendiniz yönetip abonelik olayları ile analitik göndermek için Adapty kullanıyorsanız Observer modunu etkinleştirin.
:::important
Observer modunda çalışırken Adapty SDK hiçbir işlemi kapatmaz; bu nedenle bunu kendiniz yönettiğinizden emin olun.
:::
```swift showLineNumbers
@main
struct YourApp: App {
init() {
// Configure Adapty SDK
let configurationBuilder = AdaptyConfiguration
.builder(withAPIKey: "YOUR_PUBLIC_SDK_KEY") // Get from Adapty dashboard
.with(observerMode: true)
let config = configurationBuilder.build()
// Activate Adapty SDK asynchronously
Task {
do {
try await Adapty.activate(with: configurationBuilder)
} catch {
// Handle error appropriately for your app
print("Adapty activation failed: ", error)
}
}
var body: some Scene {
WindowGroup {
// Your content view
}
}
}
}
```
```swift showLineNumbers
Task {
do {
let configurationBuilder = AdaptyConfiguration
.builder(withAPIKey: "YOUR_PUBLIC_SDK_KEY") // Get from Adapty dashboard
.with(observerMode: true)
let config = configurationBuilder.build()
try await Adapty.activate(with: config)
} catch {
// Handle error appropriately for your app
print("Adapty activation failed: ", error)
}
}
```
Parametreler:
| Parametre | Açıklama |
| --------------------------- | ------------------------------------------------------------ |
| observerMode | [Observer modunu](observer-vs-full-mode) kontrol eden boolean değer. Varsayılan değer `false`'tur. |
## Observer Modunda Adapty paywall'larını kullanma \{#using-adapty-paywalls-in-observer-mode\}
Adapty'nin paywall'larını ve A/B testi özelliklerini de kullanmak istiyorsanız bunu yapabilirsiniz — ancak Observer modunda bazı ek kurulum adımları gereklidir. Yukarıdaki adımlara ek olarak şunları yapmanız gerekir:
1. [Remote config paywall'ları](present-remote-config-paywalls) için paywall'ları normalde olduğu gibi gösterin. Paywall Builder paywall'ları için [iOS](ios-present-paywall-builder-paywalls-in-observer-mode)'a özel kurulum kılavuzunu izleyin.
3. Paywall'ları satın alma işlemleriyle [ilişkilendirin](report-transactions-observer-mode).
---
# File: report-transactions-observer-mode
---
---
title: "iOS SDK'da Observer Mode'da işlemleri bildirme"
description: "iOS SDK'da kullanıcı içgörüleri ve gelir takibi için Adapty Observer Mode'da satın alma işlemlerini bildirin."
---
Observer Mode'da Adapty SDK, mevcut satın alma sisteminiz üzerinden gerçekleştirilen işlemleri kendi başına takip edemez. App Store'dan gelen işlemleri manuel olarak bildirmeniz gerekir. Analizlerde hata oluşmaması için uygulamanızı yayınlamadan **önce** bu adımı tamamlamanız çok önemlidir.
Her işlemi Adapty'nin tanıyabilmesi için `reportTransaction` kullanın.
:::warning
**İşlem bildirmeyi atlamayın!**
`reportTransaction` çağırmazsanız Adapty işlemi tanımaz, işlem analizlerde görünmez ve entegrasyonlara gönderilmez.
:::
Adapty paywalllarını kullanıyorsanız, işlemi bildirirken `variationId` değerini de ekleyin. Bu, satın almayı tetikleyen paywalla bağlar ve paywall analizlerinin doğru çalışmasını sağlar.
```swift showLineNumbers
do {
// every time when calling transasction.finish()
try await Adapty.reportTransaction(transaction, withVariationId: )
} catch {
// handle the error
}
```
Parametreler:
| Parametre | Zorunluluk | Açıklama |
| --------------- | ---------- | --------------------------------------------------------- |
| **transaction** | zorunlu |
StoreKit 1 için: SKPaymentTransaction.
StoreKit 2 için: Transaction.
|
| **variationId** | isteğe bağlı | Paywall varyantının benzersiz kimliği. [AdaptyPaywall](https://swift.adapty.io/documentation/adapty/adaptypaywall) nesnesinin `variationId` özelliğinden alabilirsiniz. |
Observer Mode'da Adapty SDK, mevcut satın alma sisteminiz üzerinden gerçekleştirilen işlemleri kendi başına takip edemez. App Store'dan gelen işlemleri bildirmeniz veya geri yüklemeniz gerekir. Analizlerde hata oluşmaması için uygulamanızı yayınlamadan **önce** bu adımı tamamlamanız çok önemlidir.
İşlem verilerini Adapty'ye göndermek için `reportTransaction` kullanın.
:::warning
**İşlem bildirmeyi atlamayın!**
`reportTransaction` çağırmazsanız Adapty işlemi tanımaz, işlem analizlerde görünmez ve entegrasyonlara gönderilmez.
:::
Adapty paywalllarını kullanıyorsanız, işlemi bildirirken `withVariationId` değerini de ekleyin. Bu, satın almayı tetikleyen paywalla bağlar ve paywall analizlerinin doğru çalışmasını sağlar.
```swift showLineNumbers
do {
// every time when calling transasction.finish()
try await Adapty.reportTransaction(transaction, withVariationId: )
} catch {
// handle the error
}
```
Parametreler:
| Parametre | Zorunluluk | Açıklama |
| --------------- | ---------- | --------------------------------------------------------- |
| **transaction** | zorunlu |
StoreKit 1 için: SKPaymentTransaction.
StoreKit 2 için: Transaction.
|
| **variationId** | isteğe bağlı | Paywall varyantının benzersiz kimliği. [AdaptyPaywall](https://swift.adapty.io/documentation/adapty/adaptypaywall) nesnesinin `variationId` özelliğinden alabilirsiniz. |
**İşlemleri bildirme**
- 3.1.x ve önceki sürümler App Store'daki işlemleri otomatik olarak dinler, dolayısıyla manuel bildirim gerekmez.
- 3.2 sürümü Observer Mode'u desteklemiyor.
**Paywallları işlemlerle ilişkilendirme**
Adapty SDK, satın almaları siz işlediğiniz için bunların kaynağını belirleyemez. Bu nedenle Observer Mode'da paywall ve/veya A/B testi kullanmak istiyorsanız, mobil uygulama kodunuzda App Store'dan gelen işlemi ilgili paywalla bağlamanız gerekir. Bu adımı uygulamanızı yayınlamadan önce doğru şekilde yapmazsanız analizlerde hatalara yol açar.
```swift
let variationId = paywall.variationId
// There are two overloads: for StoreKit 1 and StoreKit 2
Adapty.setVariationId(variationId, forPurchasedTransaction: transactionId) { error in
if error == nil {
// successful binding
}
}
```
İstek parametreleri:
| Parametre | Zorunluluk | Açıklama |
| ------------- | ---------- | --------------------------------------------------------- |
| variationId | zorunlu | Varyantın string kimliği. [AdaptyPaywall](https://swift.adapty.io/documentation/adapty/adaptypaywall) nesnesinin `variationId` özelliğini kullanarak alabilirsiniz. |
| transactionId | zorunlu |
|
---
# File: ios-troubleshoot-purchases
---
---
title: "iOS SDK'da satın alma sorunlarını giderme"
description: "iOS SDK'da satın alma sorunlarını giderme"
---
Bu kılavuz, iOS SDK'da satın almaları manuel olarak uygularken karşılaşılan yaygın sorunları çözmenize yardımcı olur.
## Observer modunda AdaptyError.cantMakePayments \{#adaptyelrorrcantmakepayments-in-observer-mode\}
**Sorun**: Observer modunda `makePurchase` kullanırken `AdaptyError.cantMakePayments` hatası alıyorsunuz.
**Neden**: Observer modunda satın almaları kendi tarafınızda yönetmeniz gerekir; Adapty'nin `makePurchase` metodunu kullanmamalısınız.
**Çözüm**: Satın almalar için `makePurchase` kullanıyorsanız observer modunu kapatın. Ya `makePurchase` kullanmalısınız ya da observer modunda satın almaları kendi tarafınızda yönetmelisiniz. Daha fazla ayrıntı için [Observer modunu uygulama](implement-observer-mode) sayfasına bakın.
## makePurchasesCompletionHandlers bulunamıyor \{#not-found-makepurchasescompletionhandlers\}
**Sorun**: `makePurchasesCompletionHandlers` bulunamadığına dair sorunlarla karşılaşıyorsunuz.
**Neden**: Bu durum genellikle sandbox test sorunlarıyla ilgilidir.
**Çözüm**: Yeni bir sandbox kullanıcısı oluşturun ve tekrar deneyin. Bu yöntem, sandbox ile ilgili satın alma tamamlama işleyicisi sorunlarını çoğu zaman çözer.
## Diğer sorunlar \{#other-issues\}
**Sorun**: Yukarıda ele alınmayan başka satın alma sorunları yaşıyorsunuz.
**Çözüm**: Gerekiyorsa [migration kılavuzlarını](ios-sdk-migration-guides) kullanarak SDK'yı en son sürüme güncelleyin. Pek çok sorun yeni SDK sürümlerinde çözülmüş durumdadır.
---
# File: ios-web-paywall
---
---
title: "iOS SDK'da web paywalllarını uygulama"
description: "App Store ücretleri ve denetimleri olmadan ödeme almak için bir web paywall kurun."
---
:::important
Başlamadan önce [kontrol panelinde web paywallınızı yapılandırdığınızdan](web-paywall) ve Adapty SDK 3.6.1 veya sonraki bir sürümünü yüklediğinizden emin olun.
:::
## Web paywalllarını açma \{#open-web-paywalls\}
Kendiniz geliştirdiğiniz bir paywall üzerinde çalışıyorsanız, web paywalllarını SDK metodu aracılığıyla ele almanız gerekir. `.openWebPaywall` metodu:
1. Adapty'nin belirli bir kullanıcıya gösterilen paywallı yönlendirildikleri web sayfasıyla ilişkilendirebilmesi için benzersiz bir URL oluşturur.
2. Kullanıcılarınızın uygulamaya ne zaman döndüğünü izler ve ardından profil erişim haklarının güncellenip güncellenmediğini belirlemek için kısa aralıklarla `.getProfile` isteği gönderir.
Bu sayede ödeme başarılı olup erişim hakları güncellendiğinde, abonelik uygulamada neredeyse anında etkinleşir.
```swift showLineNumbers title="Swift"
do {
try await Adapty.openWebPaywall(for: product)
} catch {
print("Failed to open web paywall: \(error)")
}
```
:::note
`openWebPaywall` metodunun iki versiyonu vardır:
1. `openWebPaywall(product)`: URL'leri paywalla göre oluşturur ve ürün verilerini de URL'lere ekler.
2. `openWebPaywall(paywall)`: URL'leri paywalla göre oluşturur ancak ürün verilerini eklemez. Adapty paywallındaki ürünler web paywallındakilerden farklı olduğunda bunu kullanın.
:::
## Hataları ele alma \{#handle-errors\}
| Hata | Açıklama | Önerilen işlem |
|-----------------------------------------|------------------------------------------------------------|-----------------------------------------------------------------------------------|
| AdaptyError.paywallWithoutPurchaseUrl | Paywall için web satın alma URL'si yapılandırılmamış | Paywallın Adapty Kontrol Paneli'nde doğru şekilde yapılandırılıp yapılandırılmadığını kontrol edin |
| AdaptyError.productWithoutPurchaseUrl | Ürünün web satın alma URL'si yok | Adapty Kontrol Paneli'nde ürün yapılandırmasını doğrulayın |
| AdaptyError.failedOpeningWebPaywallUrl | URL tarayıcıda açılamadı | Cihaz ayarlarını kontrol edin veya alternatif bir satın alma yöntemi sunun |
| AdaptyError.failedDecodingWebPaywallUrl | URL'deki parametreler düzgün şekilde kodlanamadı | URL parametrelerinin geçerli ve doğru biçimde olduğunu doğrulayın |
## Uygulama örneği \{#implementation-example\}
```swift showLineNumbers title="Swift"
class SubscriptionViewController: UIViewController {
var paywall: AdaptyPaywall?
@IBAction func purchaseButtonTapped(_ sender: UIButton) {
guard let paywall = paywall, let product = paywall.products.first else { return }
Task {
await offerWebPurchase(for: product)
}
}
func offerWebPurchase(for paywallProduct: AdaptyPaywallProduct) async {
do {
// Attempt to open web paywall
try await Adapty.openWebPaywall(for: paywallProduct)
} catch let error as AdaptyError {
switch error {
case .paywallWithoutPurchaseUrl, .productWithoutPurchaseUrl:
showAlert(message: "Web purchase is not available for this product.")
case .failedOpeningWebPaywallUrl:
showAlert(message: "Could not open web browser. Please try again.")
default:
showAlert(message: "An error occurred: \(error.localizedDescription)")
}
} catch {
showAlert(message: "An unexpected error occurred.")
}
}
// Helper methods
private func showAlert(message: String) { /* ... */ }
}
```
:::note
Kullanıcılar uygulamaya döndükten sonra, profil güncellemelerini yansıtmak için arayüzü yenileyin. `AdaptyDelegate`, profil güncelleme olaylarını alıp işleyecektir.
:::
## Web paywallları uygulama içi tarayıcıda açma \{#open-web-paywalls-in-an-in-app-browser\}
:::important
Web paywalllarını uygulama içi tarayıcıda açma özelliği Adapty SDK v3.15 sürümünden itibaren desteklenmektedir.
:::
Web paywalllar varsayılan olarak harici tarayıcıda açılır.
Kesintisiz bir kullanıcı deneyimi sunmak için web paywalllarını uygulama içi tarayıcıda açabilirsiniz. Bu sayede web satın alma sayfası uygulamanız içinde görüntülenir ve kullanıcılar uygulama değiştirmeden işlemlerini tamamlayabilir.
Bunu etkinleştirmek için `in` parametresini `.inAppBrowser` olarak ayarlayın:
```swift showLineNumbers title="Swift"
do {
try await Adapty.openWebPaywall(for: product, in: .inAppBrowser) // default – .externalBrowser
} catch {
print("Failed to open web paywall: \(error)")
}
```
---
# File: identifying-users
---
---
title: "iOS SDK'da kullanıcıları tanımlama"
description: "Kişiselleştirilmiş abonelik deneyimlerini iyileştirmek için Adapty'de kullanıcıları tanımlayın."
---
Adapty, her kullanıcı için dahili bir profil ID'si oluşturur. Ancak kendi kimlik doğrulama sisteminiz varsa, kendi Customer User ID'nizi ayarlamanız gerekir. Kullanıcıları Customer User ID'leriyle [Profiles](profiles-crm) bölümünde bulabilir ve tüm entegrasyonlara gönderilecek olan [server-side API](getting-started-with-server-side-api)'de kullanabilirsiniz.
## Yapılandırma sırasında customer user ID'yi ayarlama \{#set-customer-user-id-on-configuration\}
Yapılandırma sırasında kullanıcı ID'niz varsa, bunu `.activate()` metoduna `customerUserId` parametresi olarak geçmeniz yeterlidir:
```swift showLineNumbers
// In your AppDelegate class:
let configurationBuilder =
AdaptyConfiguration
.builder(withAPIKey: "PUBLIC_SDK_KEY")
.with(customerUserId: "YOUR_USER_ID")
do {
try await Adapty.activate(with: configurationBuilder.build())
} catch {
// handle the error
}
```
```swift showLineNumbers
// In your AppDelegate class:
let configurationBuilder =
AdaptyConfiguration
.builder(withAPIKey: "PUBLIC_SDK_KEY")
.with(customerUserId: "YOUR_USER_ID")
Adapty.activate(with: configurationBuilder.build()) { error in
// handle the error
}
```
:::tip
Adapty SDK'nın bir mobil uygulamaya nasıl entegre edildiğini gerçek bir örnekle görmek ister misiniz? Tam kurulumu, paywall'ların gösterimini, satın alma işlemlerini ve diğer temel işlevleri içeren [örnek uygulamalarımıza](sample-apps) göz atın.
:::
## Yapılandırma sonrasında customer user ID'yi ayarlama \{#set-customer-user-id-after-configuration\}
SDK yapılandırması sırasında kullanıcı ID'niz yoksa, istediğiniz zaman `.identify()` metoduyla sonradan ayarlayabilirsiniz. Bu metodun en yaygın kullanım durumları, kayıt veya giriş sonrasında kullanıcının anonim kullanıcıdan kimliği doğrulanmış kullanıcıya geçişidir.
```swift showLineNumbers
do {
try await Adapty.identify("YOUR_USER_ID")
} catch {
// handle the error
}
```
```swift showLineNumbers
Adapty.identify("YOUR_USER_ID") { error in
if let error {
// handle the error
}
}
```
İstek parametreleri:
- **Customer User ID** (zorunlu): Bir string kullanıcı tanımlayıcısı.
:::warning
Önemli kullanıcı verilerinin yeniden gönderilmesi
Kullanıcının hesabına tekrar giriş yapması gibi bazı durumlarda, Adapty'nin sunucuları o kullanıcı hakkında zaten bilgiye sahip olabilir. Bu senaryolarda Adapty SDK'sı otomatik olarak yeni kullanıcıyla çalışmaya geçer. Anonim kullanıcıya özel özellikler veya üçüncü taraf ağlardan attribution verileri gibi herhangi bir veri aktardıysanız, bu verileri tanımlanan kullanıcı için yeniden göndermeniz gerekir.
Ayrıca, yeni kullanıcının verileri farklı olabileceğinden, kullanıcıyı tanımladıktan sonra tüm paywall'ları ve ürünleri yeniden talep etmeniz gerektiğini unutmayın.
:::
## Çıkış yapma ve giriş yapma \{#logging-out-and-logging-in\}
`.logout()` metodunu çağırarak istediğiniz zaman kullanıcının oturumunu kapatabilirsiniz:
```swift showLineNumbers
do {
try await Adapty.logout()
} catch {
// handle the error
}
```
```swift showLineNumbers
Adapty.logout { error in
if error == nil {
// successful logout
}
}
```
Ardından `.identify()` metodunu kullanarak kullanıcının oturumunu açabilirsiniz.
## appAccountToken'ı ayarlama \{#set-appaccounttoken\}
[`appAccountToken`](https://developer.apple.com/documentation/storekit/product/purchaseoption/appaccounttoken(_:)), Apple'ın StoreKit 2'nin kullanıcıları uygulama yüklemeleri ve cihazlar genelinde tanımlamasına yardımcı olan bir UUID'dir.
Adapty iOS SDK 3.10.2 sürümünden itibaren, SDK'yı yapılandırırken veya bir kullanıcıyı tanımlarken `appAccountToken` değerini geçebilirsiniz:
```swift showLineNumbers
// During configuration:
let configurationBuilder =
AdaptyConfiguration
.builder(withAPIKey: "PUBLIC_SDK_KEY")
.with(customerUserId: "YOUR_USER_ID", withAppAccountToken: UUID())
do {
try await Adapty.activate(with: configurationBuilder.build())
} catch {
// handle the error
}
// Or when identifying a user:
do {
try await Adapty.identify("YOUR_USER_ID", withAppAccountToken: UUID())
} catch {
// handle the error
}
```
```swift showLineNumbers
// During configuration:
let configurationBuilder =
AdaptyConfiguration
.builder(withAPIKey: "PUBLIC_SDK_KEY")
.with(customerUserId: "YOUR_USER_ID", withAppAccountToken: UUID())
Adapty.activate(with: configurationBuilder.build()) { error in
// handle the error
}
// Or when identifying a user:
Adapty.identify("YOUR_USER_ID", withAppAccountToken: UUID()) { error in
if let error {
// handle the error
}
}
```
Ardından `.identify()` metodunu kullanarak kullanıcının oturumunu açabilirsiniz.
## Cihazlar Arası Kullanıcı Tespiti \{#detect-users-across-devices\}
SDK etkinleştirildiğinde, StoreKit (iOS) veya Google Play Billing (Android) üzerinden kullanıcının mevcut haklarını otomatik olarak okur ve bunları Adapty backend'iyle senkronize eder. Aktif bir abonelik, uygulamanın `restorePurchases` çağrısı yapmadan Adapty profilinde görünür.
Otomatik olarak **gerçekleşmeyen** şey, yeni bir cihazdaki profilin orijinal cihazdaki profille aynı kullanıcıya ait olduğunun tanınmasıdır. Adapty, profilleri Customer User ID ile eşleştirir; dolayısıyla kimlik sürekliliği CUID olarak ne kullandığınıza bağlıdır.
**Adapty'nin cihazlar arasında neleri algılayabildiği**
| Kurulumunuz | Adapty'nin algıladığı | Yapmanız gereken |
| --- | --- | --- |
| Customer User ID = `device_id` (uygulama girişi yok) | Yeni cihaz farklı bir CUID ve dolayısıyla farklı bir profil alır. Abonelik, **Access level updated** olayı aracılığıyla yeni profile senkronize edilir; ancak `subscription_started` tetiklenmez — yeni profil, orijinal satın almanın devralıcısı olarak değerlendirilir. `subscription_started` üzerine kurulu analizler, geri dönen kullanıcıları eksik sayar. | Geri dönen bir kullanıcının cihazlar arasında mevcut profille eşleşmesi için Customer User ID olarak kararlı bir hesap kimliği kullanın. |
| Customer User ID = kararlı hesap kimliği (her cihazda oturum açma) | SDK, `activate()` sırasında aboneliği otomatik olarak senkronize eder ve `identify()`, CUID ile mevcut profili eşleştirir. | Ek kurulum gerekmez — hem kimlik hem de abonelik otomatik olarak çözümlenir. |
| Apple Family Sharing devralıcısı | Aile üyesi, aboneliği yalnızca **Access level updated** olayı aracılığıyla alır — `subscription_started` tetiklenmez. | **Access level updated** olayını dinleyin. Tam olay matrisi için [Apple Family Sharing](apple-family-sharing) sayfasına bakın. |
| Aynı Apple/Google hesabı, farklı uygulama içi kullanıcılar | Satın almayı kaydeden ilk profil üst profil olur. Sonraki profiller, tek bir **Access level updated** olayıyla bir devralıcı zinciri aracılığıyla aboneliği görür. | Oturum açmayı zorunlu kılın, ardından modelinize uygun bir [paylaşım modu](sharing-paid-access-between-user-accounts) seçin. |
**Yeni bir cihazda satın almaları geri yükleme**
Paywallınızda kullanıcı tarafından başlatılan bir "Satın almaları geri yükle" butonu gösterin. Apple App Review (kural 3.1.1) bunu zorunlu kılar ve otomatik senkronizasyonun uç bir durumu kaçırması halinde yedek olarak işlev görür. Buton, SDK'nızda `restorePurchases` çağrısı yapmalıdır.
İlk açılışta programatik bir `restorePurchases` çağrısı normal kullanım için gerekli değildir — SDK, `activate()` sırasında zaten eşdeğerini çalıştırır. Programatik çağrıları yalnızca zorunlu bir güncel makbuz kontrolü için ayırın; örneğin `activate()` tamamlandıktan sonra eksik erişimi hata ayıklarken.
---
# File: setting-user-attributes
---
---
title: "iOS SDK'da kullanıcı özelliklerini ayarlama"
description: "Daha iyi kitle segmentasyonu için Adapty'de kullanıcı özelliklerini nasıl ayarlayacağınızı öğrenin."
---
Uygulamanızın kullanıcılarına e-posta, telefon numarası gibi isteğe bağlı özellikler ekleyebilirsiniz. Bu özellikleri kullanıcı [segmentleri](segments) oluşturmak veya CRM'de görüntülemek için kullanabilirsiniz.
### Kullanıcı özelliklerini ayarlama \{#setting-user-attributes\}
Kullanıcı özelliklerini ayarlamak için `.updateProfile()` metodunu çağırın:
```swift showLineNumbers
let builder = AdaptyProfileParameters.Builder()
.with(email: "email@email.com")
.with(phoneNumber: "+18888888888")
.with(firstName: "John")
.with(lastName: "Appleseed")
.with(gender: .other)
.with(birthday: Date())
do {
try await Adapty.updateProfile(params: builder.build())
} catch {
// handle the error
}
```
```swift showLineNumbers
let builder = AdaptyProfileParameters.Builder()
.with(email: "email@email.com")
.with(phoneNumber: "+18888888888")
.with(firstName: "John")
.with(lastName: "Appleseed")
.with(gender: .other)
.with(birthday: Date())
Adapty.updateProfile(params: builder.build()) { error in
if error != nil {
// handle the error
}
}
```
`updateProfile` metoduyla daha önce ayarladığınız özellikler sıfırlanmaz.
:::tip
Adapty SDK'nın bir mobil uygulamaya nasıl entegre edildiğini gerçek bir örnekle görmek ister misiniz? Tam kurulumu, paywall'ların gösterimini, satın alma işlemlerini ve diğer temel işlevleri içeren [örnek uygulamalarımıza](sample-apps) göz atın.
:::
### İzin verilen anahtar listesi \{#the-allowed-keys-list\}
`AdaptyProfileParameters.Builder` için izin verilen anahtarlar `` ve değerler `` aşağıda listelenmiştir:
| Anahtar | Değer |
|---|-----|
|
email
phoneNumber
firstName
lastName
| String |
| gender | Enum, izin verilen değerler: `female`, `male`, `other` |
| birthday | Date |
### Özel kullanıcı özellikleri \{#custom-user-attributes\}
Kendi özel özelliklerinizi tanımlayabilirsiniz. Bunlar genellikle uygulamanızın kullanımıyla ilgilidir. Örneğin; fitness uygulamalarında haftalık egzersiz sayısı, dil öğrenme uygulamalarında kullanıcının bilgi düzeyi gibi. Bu özellikleri, hedefli paywall'lar ve teklifler oluşturmak için segmentlerde; hangi ürün metriklerinin geliri en çok etkilediğini anlamak için de analitikte kullanabilirsiniz.
```swift showLineNumbers
do {
builder = try builder.with(customAttribute: "value1", forKey: "key1")
} catch {
// handle key/value validation error
}
```
Mevcut bir anahtarı kaldırmak için `.withRemoved(customAttributeForKey:)` metodunu kullanın:
```swift showLineNumbers
do {
builder = try builder.withRemoved(customAttributeForKey: "key2")
} catch {
// handle error
}
```
Bazen daha önce hangi özel özelliklerin ayarlandığını öğrenmeniz gerekebilir. Bunun için `AdaptyProfile` nesnesinin `customAttributes` alanını kullanın.
:::warning
`customAttributes` değerinin güncel olmayabileceğini unutmayın; kullanıcı özellikleri farklı cihazlardan herhangi bir zamanda gönderilebileceğinden, sunucudaki özellikler son senkronizasyondan bu yana değişmiş olabilir.
:::
### Sınırlar \{#limits\}
- Kullanıcı başına en fazla 30 özel özellik
- Anahtar adları en fazla 30 karakter olabilir. Anahtar adı alfanümerik karakterler ve şu karakterlerden herhangi birini içerebilir: `_` `-` `.`
- Değer, en fazla 50 karakter uzunluğunda bir string veya float olabilir.
---
# File: subscription-status
---
---
title: "iOS SDK'da abonelik durumunu kontrol etme"
description: "Müşteri tutunumunu artırmak için Adapty'de kullanıcı abonelik durumunu takip edin ve yönetin."
---
Adapty ile abonelik durumunu takip etmek çok kolaydır. Ürün kimliklerini kodunuza elle girmenize gerek yoktur. Bunun yerine, aktif bir [access level](access-level) olup olmadığını kontrol ederek kullanıcının abonelik durumunu zahmetsizce doğrulayabilirsiniz.
Abonelik durumunu kontrol etmeye başlamadan önce [App Store Server Notifications](enable-app-store-server-notifications) ayarlarını yapın.
## Access level ve AdaptyProfile nesnesi \{#access-level-and-the-adaptyprofile-object\}
Access level'lar, [AdaptyProfile](https://swift.adapty.io/documentation/adapty/adaptyprofile) nesnesinin özelliklerdir. Profili; uygulamanız başladığında, örneğin [bir kullanıcıyı tanımladığınızda](identifying-users#set-customer-user-id-on-configuration), alıp değişiklik olduğunda güncellemenizi öneririz. Bu sayede profil nesnesini defalarca istek atmadan kullanabilirsiniz.
Profil güncellemelerinden haberdar olmak için, aşağıdaki [Abonelik durumu güncellemelerini dinleme](subscription-status#listening-for-subscription-status-updates) bölümünde açıklandığı gibi profil değişikliklerini dinleyin.
:::tip
Adapty SDK'nın bir mobil uygulamaya nasıl entegre edildiğini gerçek bir örnekle görmek ister misiniz? Tam kurulumu, paywall'ların gösterimini, satın alma işlemlerini ve diğer temel işlevleri içeren [örnek uygulamalarımıza](sample-apps) göz atın.
:::
## Access level'ı sunucudan alma \{#retrieving-the-access-level-from-the-server\}
Access level'ı sunucudan almak için `.getProfile()` metodunu kullanın:
```swift showLineNumbers
do {
let profile = try await Adapty.getProfile()
if profile.accessLevels["YOUR_ACCESS_LEVEL"]?.isActive ?? false {
// grant access to premium features
}
} catch {
// handle the error
}
```
```swift showLineNumbers
Adapty.getProfile { result in
if let profile = try? result.get() {
// check the access
profile.accessLevels["YOUR_ACCESS_LEVEL"]?.isActive ?? false {
// grant access to premium features
}
}
}
```
Yanıt parametreleri:
| Parametre | Açıklama |
| --------- |------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Profile |
Bir [AdaptyProfile](https://swift.adapty.io/documentation/adapty/adaptyprofile) nesnesi. Genel olarak, kullanıcının uygulamaya premium erişimi olup olmadığını belirlemek için yalnızca profilin access level durumunu kontrol etmeniz yeterlidir.
`.getProfile` metodu her zaman API'yi sorgulamaya çalıştığından en güncel sonucu döndürür. Herhangi bir nedenle (ör. internet bağlantısı yoksa) Adapty SDK sunucudan bilgi alamazsa, önbelleğe alınmış veriler döndürülür. Ayrıca Adapty SDK, `AdaptyProfile` önbelleğini düzenli aralıklarla güncelleyerek bu bilgilerin mümkün olduğunca güncel kalmasını sağlar.
|
`.getProfile()` metodu size kullanıcı profilini döndürür; bu profil üzerinden access level durumunu öğrenebilirsiniz. Bir uygulamada birden fazla access level tanımlayabilirsiniz. Örneğin, bir gazete uygulamanız varsa ve farklı konulara bağımsız abonelikler satıyorsanız "sports" ve "science" adında access level'lar oluşturabilirsiniz. Ancak çoğu zaman yalnızca bir access level'a ihtiyaç duyarsınız; böyle durumlarda varsayılan "premium" access level'ı kullanabilirsiniz.
Varsayılan "premium" access level'ını kontrol etmek için bir örnek:
```swift showLineNumbers
do {
let profile = try await Adapty.getProfile()
let isPremium = profile.accessLevels["premium"]?.isActive ?? false
// grant access to premium features
} catch {
// handle the error
}
```
```swift showLineNumbers
Adapty.getProfile { result in
if let profile = try? result.get(),
profile.accessLevels["premium"]?.isActive ?? false {
// grant access to premium features
}
}
```
### Abonelik durumu güncellemelerini dinleme \{#listening-for-subscription-status-updates\}
Kullanıcının aboneliği her değiştiğinde Adapty bir olay tetikler.
Adapty'den mesaj alabilmek için bazı ek yapılandırmalar yapmanız gerekir:
```swift showLineNumbers
Adapty.delegate = self
// To receive subscription updates, extend `AdaptyDelegate` with this method:
nonisolated func didLoadLatestProfile(_ profile: AdaptyProfile) {
// handle any changes to subscription state
}
```
Adapty, uygulama başlangıcında da bir olay tetikler. Bu durumda önbelleğe alınmış abonelik durumu iletilir.
### Abonelik durumu önbelleği \{#subscription-status-cache\}
Adapty SDK'daki önbellek, profilin abonelik durumunu saklar. Bu sayede sunucuya erişilemese bile önbelleğe alınan veriler kullanılarak profil abonelik durumu hakkında bilgi edinilebilir.
Ancak önbellekten doğrudan veri isteği yapılamayacağını belirtmek gerekir. SDK, profilde herhangi bir güncelleme veya değişiklik olup olmadığını kontrol etmek için sunucuyu her dakika periyodik olarak sorgular. Yeni işlemler veya başka güncellemeler gibi değişiklikler varsa, bunlar sunucuyla senkronize kalması için önbelleğe alınan verilere yansıtılır.
---
# File: ios-deal-with-att
---
---
title: "iOS SDK'da ATT ile Başa Çıkma"
description: "Abonelik kurulumunu ve yönetimini kolaylaştırmak için iOS'ta Adapty'yi kullanmaya başlayın."
---
Uygulamanız AppTrackingTransparency çerçevesini kullanıyor ve kullanıcıya uygulama izleme yetkilendirme isteği sunuyorsa, [yetkilendirme durumunu](https://developer.apple.com/documentation/apptrackingtransparency/attrackingmanager/authorizationstatus/) Adapty'ye göndermeniz gerekir.
```swift showLineNumbers
let builder = AdaptyProfileParameters.Builder()
.with(appTrackingTransparencyStatus: .authorized)
do {
try await Adapty.updateProfile(params: builder.build())
} catch {
// handle the error
}
```
```swift showLineNumbers
if #available(iOS 14, macOS 11.0, *) {
let builder = AdaptyProfileParameters.Builder()
.with(appTrackingTransparencyStatus: .authorized)
Adapty.updateProfile(params: builder.build()) { [weak self] error in
if error != nil {
// handle the error
}
}
}
```
:::warning
Bu değeri değiştiği anda mümkün olan en kısa sürede göndermenizi şiddetle tavsiye ederiz; yalnızca bu durumda veriler, yapılandırdığınız entegrasyonlara zamanında iletilir.
:::
---
# File: kids-mode
---
---
title: "iOS SDK'da Çocuk Modu"
description: "Apple politikalarına uymak için Çocuk Modunu kolayca etkinleştirin. iOS SDK'da IDFA veya reklam verisi toplanmaz."
---
iOS uygulamanız çocuklara yönelikse [Apple](https://developer.apple.com/kids/) politikalarına uymanız gerekir. Adapty SDK kullanıyorsanız, birkaç basit adımla SDK'yı bu politikalara uygun şekilde yapılandırabilir ve uygulama mağazası incelemelerinden geçebilirsiniz.
## Neler gerekli? \{#whats-required\}
Aşağıdaki verilerin toplanmasını devre dışı bırakmak için Adapty SDK'yı yapılandırmanız gerekir:
- [IDFA (Reklamverenler için Tanımlayıcı)](https://en.wikipedia.org/wiki/Identifier_for_Advertisers)
- [IP adresi](https://www.ftc.gov/system/files/ftc_gov/pdf/p235402_coppa_application.pdf)
Ayrıca müşteri kullanıcı kimliğini dikkatli kullanmanızı öneririz. `` formatındaki kullanıcı kimliği, e-posta kullanımı gibi kişisel veri toplama olarak değerlendirilecektir. Çocuk Modu için en iyi uygulama, uyumluluğu sağlamak amacıyla rastgele oluşturulmuş veya anonimleştirilmiş tanımlayıcılar (ör. hash'lenmiş kimlikler veya cihaz tarafından oluşturulan UUID'ler) kullanmaktır.
## Kids Modunu Etkinleştirme \{#enabling-kids-mode\}
### Adapty Kontrol Paneli'ndeki Güncellemeler \{#updates-in-the-adapty-dashboard\}
Adapty Kontrol Paneli'nde IP adresi toplamasını devre dışı bırakmanız gerekiyor. Bunun için [App settings](https://app.adapty.io/settings/general) sayfasına gidin ve **Collect users' IP address** altındaki **Disable IP address collection** seçeneğine tıklayın.
### Mobil uygulama kodunuzdaki güncellemeler \{#updates-in-your-mobile-app-code\}
SDK 4.0 ile birlikte Kids Mode, `KidsMode` adında bir Swift package trait'idir. Bu trait etkinleştirildiğinde, IDFA ve AdSupport tüm SDK genelinde derleme aşamasında devre dışı bırakılır; normal **Adapty** ve **AdaptyUI** modüllerini ve `import Adapty` / `import AdaptyUI` ifadelerini kullanmaya devam edersiniz.
:::note
`KidsMode` trait'i SDK 4.0 sürümünden itibaren kullanılabilir. SDK 4.0'dan itibaren SDK yalnızca Swift Package Manager aracılığıyla kurulmaktadır — CocoaPods artık desteklenmemektedir.
:::
1. [Adapty SDK'yı](sdk-installation-ios) her zamanki gibi yükleyin; standart **Adapty** ve **AdaptyUI** modüllerini seçin.
2. Xcode 26.4 veya sonraki sürümlerde proje ayarlarınızı açın, **Package Dependencies** görünümüne gidin ve AdaptySDK-iOS bağımlılığı için **KidsMode** trait'ini etkinleştirin.
:::note
Xcode 26.4'ten önceki sürümler, bir Xcode projesinde kullanıcı arayüzü üzerinden trait'leri etkinleştiremez. Bu durumda, `KidsMode` trait'i etkinleştirilmiş şekilde Adapty'ye bağımlı küçük bir yerel Swift paketi oluşturun (**Package.swift** sekmesine bakın) ve uygulama hedefinizi bu pakete bağımlı yapın.
:::
Adapty'yi `Package.swift` dosyasında bağımlılık olarak ekliyorsanız, trait'i paket bildiriminde etkinleştirin. Trait'ler için `swift-tools-version` 6.1 veya üstü gereklidir.
```swift showLineNumbers title="Package.swift"
.package(
url: "https://github.com/adaptyteam/AdaptySDK-iOS.git",
from: "4.0.0",
traits: ["KidsMode"]
)
```
iOS uygulamanız çocuklara yönelikse [Apple](https://developer.apple.com/kids/) politikalarına uymanız gerekir. Adapty SDK kullanıyorsanız, birkaç basit adımla bu politikaları karşılayacak şekilde yapılandırabilir ve uygulama mağazası incelemelerinden geçebilirsiniz.
## Neler gerekli? \{#whats-required\}
Adapty SDK'yı aşağıdakilerin toplanmasını devre dışı bırakacak şekilde yapılandırmanız gerekir:
- [IDFA (Reklamverenler için Tanımlayıcı)](https://en.wikipedia.org/wiki/Identifier_for_Advertisers)
- [IP adresi](https://www.ftc.gov/system/files/ftc_gov/pdf/p235402_coppa_application.pdf)
Ayrıca, müşteri kullanıcı kimliğini dikkatli kullanmanızı öneririz. `` biçimindeki kullanıcı kimliği, e-posta kullanımında olduğu gibi kişisel veri toplama olarak değerlendirilecektir. Çocuk Modu için en iyi uygulama, uyumluluğu sağlamak amacıyla rastgele oluşturulmuş veya anonimleştirilmiş tanımlayıcılar (örneğin, karma kimlikler veya cihaz tarafından üretilen UUID'ler) kullanmaktır.
## Çocuk Modunu Etkinleştirme \{#enabling-kids-mode\}
### Adapty Kontrol Paneli'nde Yapılacak Güncellemeler \{#updates-in-the-adapty-dashboard\}
Adapty Kontrol Paneli'nde IP adresi toplama özelliğini devre dışı bırakmanız gerekiyor. Bunun için [App settings](https://app.adapty.io/settings/general) sayfasına gidin ve **Collect users' IP address** altındaki **Disable IP address collection** seçeneğine tıklayın.
### Mobil uygulama kodunuzda yapılacak güncellemeler \{#updates-in-your-mobile-app-code\}
Politikalara uymak için kullanıcının IDFA'sı ve IP adresi toplanmasını devre dışı bırakın.
Swift Package Manager kullanıyorsanız, SDK'yı yüklerken Xcode'da **Adapty_KidsMode** modülünü seçerek Kids Mode'u etkinleştirebilirsiniz.
Xcode'da **File** -> **Add Package Dependency...** yolunu izleyin. Paket bağımlılığı ekleme adımları Xcode sürümleri arasında farklılık gösterebileceğinden, gerekirse Xcode belgelerine başvurun.
1. Depo URL'sini girin:
```
https://github.com/adaptyteam/AdaptySDK-iOS.git
```
2. Sürümü seçin (en son kararlı sürüm önerilir) ve **Add Package** düğmesine tıklayın.
3. **Choose Package Products** penceresinde ihtiyacınız olan modülleri seçin:
- **Adapty_KidsMode** (çekirdek modül)
- **AdaptyUI_KidsMode** (isteğe bağlı - yalnızca Paywall Builder kullanmayı planlıyorsanız)
Başka paketlere ihtiyacınız olmayacak.
4. Kurulumu tamamlamak için **Add Package** düğmesine tıklayın.
5. Kodunuzda `import Adapty` yerine `import Adapty_KidsMode`, `import AdaptyUI` yerine `import AdaptyUI_KidsMode` yazın:
```swift
```
1. Podfile dosyanızı güncelleyin:
- Eğer `post_install` bölümünüz **yoksa**, aşağıdaki kod bloğunun tamamını ekleyin.
- Eğer `post_install` bölümünüz **varsa**, vurgulanan satırları mevcut bölümle birleştirin.
```ruby showLineNumbers title="Podfile"
def adapty_enable_kids_mode(installer)
installer.pods_project.targets.each do |target|
next unless target.name == 'Adapty'
target.build_configurations.each do |config|
flags = config.build_settings['OTHER_SWIFT_FLAGS'] || '$(inherited)'
flags = flags.join(' ') if flags.is_a?(Array)
config.build_settings['OTHER_SWIFT_FLAGS'] = "#{flags} -DADAPTY_KIDS_MODE"
end
target.frameworks_build_phase.files.dup.each do |bf|
target.frameworks_build_phase.remove_build_file(bf) if bf.display_name.to_s.include?('AdSupport')
end
end
installer.pods_project.save
Dir.glob(File.join(installer.sandbox.root, 'Target Support Files', '**', '*.xcconfig')).each do |xc|
File.write(xc, File.read(xc).gsub(/\s*-framework\s+"?AdSupport"?/, ''))
end
end
post_install do |installer|
# ... keep your existing post_install body (Flutter adds one automatically) ...
adapty_enable_kids_mode(installer) # <-- enable Adapty Kids Mode
end
```
2. Değişiklikleri uygulamak için aşağıdaki komutu çalıştırın:
```sh showLineNumbers title="Shell"
pod install
```
---
# File: get-onboardings
---
---
title: "Onboarding'leri ve yapılandırmalarını getir"
description: "Adapty'de onboarding'leri nasıl alacağınızı öğrenin."
---
:::tip
**SDK v4 itibarıyla**, onboarding'lere daha güçlü bir alternatif olarak [flow'lar](get-pb-paywalls) oluşturabilirsiniz. WebView içinde çalışan onboarding'lerin aksine, flow'lar cihazda nativ olarak render edilir; bu sayede daha akıcı animasyonlar, tutarlı bir iOS görünümü, daha hızlı yükleme süreleri ve WebView bağımlılığı olmadan çalışma imkânı sunar. Başlamak için [Flow'ları ve paywall'ları alma](get-pb-paywalls) ve [Flow'ları ve paywall'ları gösterme](ios-present-paywalls) sayfalarına bakın.
:::
[Adapty Kontrol Paneli'ndeki builder ile onboarding'inizin görsel kısmını tasarladıktan](design-onboarding) sonra, bunu mobil uygulamanızda gösterebilirsiniz. Bu sürecin ilk adımı, aşağıda açıklandığı gibi placement ile ilişkili onboarding'i ve görünüm yapılandırmasını almaktır.
Başlamadan önce şunları kontrol edin:
1. [Adapty iOS, Android, React Native veya Flutter SDK](installation-of-adapty-sdks) sürüm 3.8.0 veya üzerini yüklemiş olmanız gerekir.
2. [Bir onboarding oluşturmuş](create-onboarding) olmanız gerekir.
3. Onboarding'i bir [placement](placements)'a eklemiş olmanız gerekir.
## Onboarding'i getir \{#fetch-onboarding\}
No-code oluşturucumuzla bir [onboarding](onboardings) oluşturduğunuzda, bu onboarding uygulamanızın getirip görüntülemesi gereken bir yapılandırma içeren konteyner olarak saklanır. Bu konteyner tüm deneyimi yönetir; hangi içeriğin görüneceğini, nasıl sunulacağını ve kullanıcı etkileşimlerinin (sınav cevapları veya form girişleri gibi) nasıl işleneceğini belirler. Konteyner aynı zamanda analitik olaylarını otomatik olarak takip eder, bu nedenle ayrıca görüntüleme takibi yapmanıza gerek yoktur.
En iyi performans için, kullanıcılara göstermeden önce görsellerin indirilmesine yetecek süreyi tanımak amacıyla onboarding yapılandırmasını erken getirin.
Bir onboarding almak için `getOnboarding` metodunu kullanın:
```swift showLineNumbers
do {
let onboarding = try await Adapty.getOnboarding(placementId: "YOUR_PLACEMENT_ID")
// the requested onboarding
} catch {
// handle the error
}
```
Parametreler:
| Parametre | Zorunluluk | Açıklama |
|---------|--------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| **placementId** | zorunlu | İstenen [Placement](placements)'ın tanımlayıcısı. Bu, Adapty Kontrol Paneli'nde placement oluştururken belirttiğiniz değerdir. |
| **locale** |
isteğe bağlı
varsayılan: `en`
|
Onboarding lokalizasyonunun tanımlayıcısı. Bu parametrenin, eksi (**-**) karakteriyle ayrılmış bir veya iki alt etiket içeren bir dil kodu olması beklenmektedir. İlk alt etiket dil için, ikincisi bölge içindir.
Örnek: `en` İngilizce anlamına gelir, `pt-br` Brezilya Portekizcesini temsil eder.
Dil kodları ve bunların nasıl kullanılması önerildiği hakkında daha fazla bilgi için [Lokalizasyonlar ve dil kodları](localizations-and-locale-codes) sayfasına bakın.
SDK varsayılan olarak sunucudan veri yüklemeye çalışır ve hata durumunda önbelleğe alınmış veriyi döndürür. Kullanıcılarınızın her zaman en güncel veriyi almasını sağladığı için bu seçeneği öneriyoruz.
Ancak kullanıcılarınızın kararsız bir internet bağlantısıyla başa çıktığını düşünüyorsanız, önbelleğe alınmış veriyi döndürmek için `.returnCacheDataElseLoad` kullanmayı düşünün. Bu senaryoda kullanıcılar en güncel veriyi alamayabilir, ancak internet bağlantısı ne kadar kesintili olursa olsun daha hızlı yükleme süresi yaşarlar. Önbellek düzenli olarak güncellenir, bu nedenle ağ isteklerini önlemek amacıyla oturum sırasında kullanmak güvenlidir.
Önbelleğin uygulama yeniden başlatıldığında bozulmadan kaldığını ve yalnızca uygulama yeniden yüklendiğinde veya manuel temizleme yapıldığında silindiğini unutmayın.
Adapty SDK, onboarding'leri yerel olarak iki katmanda saklar: yukarıda açıklanan düzenli olarak güncellenen önbellek ve yedek onboarding'ler. Onboarding'leri daha hızlı getirmek için CDN ve CDN'e ulaşılamadığında bağımsız bir yedek sunucu kullanıyoruz. Bu sistem, internet bağlantısının yetersiz olduğu durumlarda bile güvenilirliği sağlarken her zaman onboarding'lerinizin en güncel sürümünü almanızı garanti etmek için tasarlanmıştır.
|
| **loadTimeout** | varsayılan: 5 sn |
Bu değer, metodun zaman aşımını sınırlar. Zaman aşımına ulaşılırsa önbelleğe alınmış veri veya yerel yedek döndürülür.
Nadiren de olsa bu metodun `loadTimeout` içinde belirtilenden biraz daha geç zaman aşımına uğrayabileceğini unutmayın; çünkü işlem arka planda farklı isteklerden oluşabilir.
|
Yanıt parametreleri:
| Parametre | Açıklama |
|:----------|:-----------------------------------------------------------------------------------------------------------------------------------------------------------|
| Onboarding | Onboarding tanımlayıcısı ve yapılandırması, remote config ve diğer çeşitli özellikler içeren bir [`AdaptyOnboarding`](https://swift.adapty.io/documentation/adapty/adaptyonboarding) nesnesi. |
## Varsayılan kitle onboarding'i ile onboarding getirmeyi hızlandır \{#speed-up-onboarding-fetching-with-default-audience-onboarding\}
Genellikle onboarding'ler neredeyse anında getirilir, bu nedenle bu süreci hızlandırma konusunda endişelenmenize gerek yoktur. Ancak çok sayıda kitle ve onboarding'iniz varken kullanıcılarınızın internet bağlantısı zayıfsa, onboarding getirme işlemi istediğinizden daha uzun sürebilir. Böyle durumlarda, hiç onboarding göstermemek yerine sorunsuz bir kullanıcı deneyimi sağlamak amacıyla varsayılan bir onboarding görüntülemek isteyebilirsiniz.
Bu sorunu çözmek için, belirtilen placement'ın **All Users** kitlesi için onboarding'i getiren `getOnboardingForDefaultAudience` metodunu kullanabilirsiniz. Ancak, önerilen yaklaşımın yukarıdaki [Onboarding'i Getir](#fetch-onboarding) bölümünde açıklandığı gibi `getOnboarding` metoduyla onboarding getirmek olduğunu anlamak çok önemlidir.
:::warning
`getOnboardingForDefaultAudience` yerine `getOnboarding` kullanmayı düşünün; çünkü birincisinin önemli kısıtlamaları vardır:
- **Uyumluluk sorunları**: Birden fazla uygulama sürümünü desteklerken sorunlar yaratabilir; ya geriye dönük uyumlu tasarımlar yapmanızı ya da eski sürümlerin yanlış görünebileceğini kabul etmenizi gerektirir.
- **Kişiselleştirme yok**: Yalnızca "All Users" kitlesi için içerik gösterir; ülke, attribution veya özel özniteliklere dayalı hedeflemeyi ortadan kaldırır.
Kullanım durumunuzda daha hızlı getirme bu dezavantajlardan daha önemliyse, aşağıda gösterildiği gibi `getOnboardingForDefaultAudience` kullanın. Aksi takdirde, [yukarıda](#fetch-onboarding) açıklandığı gibi `getOnboarding` kullanın.
:::
```swift showLineNumbers
Adapty.getOnboardingForDefaultAudience(placementId: "YOUR_PLACEMENT_ID") { result in
switch result {
case let .success(onboarding):
// the requested onboarding
case let .failure(error):
// handle the error
}
}
```
Parametreler:
| Parametre | Zorunluluk | Açıklama |
|---------|--------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| **placementId** | zorunlu | İstenen [Placement](placements)'ın tanımlayıcısı. Bu, Adapty Kontrol Paneli'nde placement oluştururken belirttiğiniz değerdir. |
| **locale** |
isteğe bağlı
varsayılan: `en`
|
Onboarding lokalizasyonunun tanımlayıcısı. Bu parametrenin, eksi (**-**) karakteriyle ayrılmış bir veya iki alt etiket içeren bir dil kodu olması beklenmektedir. İlk alt etiket dil için, ikincisi bölge içindir.
Örnek: `en` İngilizce anlamına gelir, `pt-br` Brezilya Portekizcesini temsil eder.
Dil kodları ve bunların nasıl kullanılması önerildiği hakkında daha fazla bilgi için [Lokalizasyonlar ve dil kodları](localizations-and-locale-codes) sayfasına bakın.
SDK varsayılan olarak sunucudan veri yüklemeye çalışır ve hata durumunda önbelleğe alınmış veriyi döndürür. Kullanıcılarınızın her zaman en güncel veriyi almasını sağladığı için bu seçeneği öneriyoruz.
Ancak kullanıcılarınızın kararsız bir internet bağlantısıyla başa çıktığını düşünüyorsanız, önbelleğe alınmış veriyi döndürmek için `.returnCacheDataElseLoad` kullanmayı düşünün. Bu senaryoda kullanıcılar en güncel veriyi alamayabilir, ancak internet bağlantısı ne kadar kesintili olursa olsun daha hızlı yükleme süresi yaşarlar. Önbellek düzenli olarak güncellenir, bu nedenle ağ isteklerini önlemek amacıyla oturum sırasında kullanmak güvenlidir.
Önbelleğin uygulama yeniden başlatıldığında bozulmadan kaldığını ve yalnızca uygulama yeniden yüklendiğinde veya manuel temizleme yapıldığında silindiğini unutmayın.
Adapty SDK, onboarding'leri yerel olarak iki katmanda saklar: yukarıda açıklanan düzenli olarak güncellenen önbellek ve yedek onboarding'ler. Onboarding'leri daha hızlı getirmek için CDN ve CDN'e ulaşılamadığında bağımsız bir yedek sunucu kullanıyoruz. Bu sistem, internet bağlantısının yetersiz olduğu durumlarda bile güvenilirliği sağlarken her zaman onboarding'lerinizin en güncel sürümünü almanızı garanti etmek için tasarlanmıştır.
|
---
# File: ios-present-onboardings
---
---
title: "iOS SDK'da onboardingları sunma"
description: "iOS'ta dönüşümleri ve geliri artırmak için onboardingları nasıl sunacağınızı keşfedin."
---
:::tip
**SDK v4'ten itibaren**, onboarding'lere daha güçlü bir alternatif olarak [flow'lar](get-pb-paywalls) oluşturabilirsiniz. Onboarding'ler WebView içinde çalışırken, flow'lar cihazda yerel olarak render edilir; bu sayede daha akıcı animasyonlar, tutarlı bir iOS görünümü, daha hızlı yükleme süreleri ve WebView bağımlılığı ortadan kalkar. Başlamak için [Flow'ları ve paywall'ları edinme](get-pb-paywalls) ve [Flow'ları ve paywall'ları gösterme](ios-present-paywalls) sayfalarına göz atın.
:::
Builder ile bir onboarding özelleştirdiyseniz, bunu kullanıcıya göstermek için mobil uygulama kodunuzda ayrıca render etmenize gerek yoktur. Böyle bir onboarding, hem onboarding içinde ne gösterileceğini hem de nasıl gösterileceğini içerir.
Başlamadan önce şunları sağlayın:
1. [Adapty iOS SDK](sdk-installation-ios) 3.8.0 veya üzerini yüklemiş olun.
2. Bir [onboarding oluşturmuş](create-onboarding) olun.
3. Onboardingı bir [placement](placements)'a eklemiş olun.
## Swift'te onboardingları sunma \{#present-onboardings-in-swift\}
Görsel onboardingı cihaz ekranında göstermek için şu adımları izleyin:
1. `.getOnboardingConfiguration` metodunu kullanarak onboarding görünüm yapılandırmasını alın.
2. Görüntülemek istediğiniz görsel onboardingı `.onboardingController` metodunu kullanarak başlatın:
İstek parametreleri:
| Parametre | Zorunluluk | Açıklama |
|:--------------------------------|:-----------|:--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| **onboarding configuration** | zorunlu | Tüm onboarding özelliklerini içeren bir `AdaptyUI.OnboardingConfiguration` nesnesi. Bunu elde etmek için `AdaptyUI.getOnboardingConfiguration` metodunu kullanın. |
| **delegate** | zorunlu | Onboarding olaylarını dinlemek için bir `AdaptyOnboardingControllerDelegate`. |
Döndürür:
| Nesne | Açıklama |
|:-------------------------------|:--------------------------------------------------------|
| **AdaptyOnboardingController** | İstenen onboarding ekranını temsil eden bir nesne |
3. Nesne başarıyla oluşturulduktan sonra cihaz ekranında görüntüleyebilirsiniz:
```swift showLineNumbers title="Swift"
import Adapty
import AdaptyUI
// 0. Get an onboarding if you haven't done it yet
let onboarding = try await Adapty.getOnboarding(placementId: "YOUR_PLACEMENT_ID")
// 1. Obtain the onboarding view configuration:
let configuration = try AdaptyUI.getOnboardingConfiguration(forOnboarding: onboarding)
// 2. Create Onboarding View Controller
let onboardingController = try AdaptyUI.onboardingController(
with: configuration,
delegate:
)
// 3. Present it to the user
present(onboardingController, animated: true)
```
## SwiftUI'da onboardingları sunma \{#present-onboardings-in-swiftui\}
SwiftUI'da görsel onboardingı cihaz ekranında göstermek için:
```swift showLineNumbers title="SwiftUI"
// 1. Obtain the onboarding view configuration:
let configuration = try AdaptyUI.getOnboardingConfiguration(forOnboarding: onboarding)
// 2. Display the Onboarding View within your view hierarchy
AdaptyOnboardingView(
configuration: configuration,
placeholder: { Text("Your Placeholder View") },
onCloseAction: { action in
// hide the onboarding view
},
onError: { error in
// handle the error
}
)
```
## Splash ekranı ile onboarding arasına yumuşak geçiş ekleme \{#add-smooth-transitions-between-the-splash-screen-and-onboarding\}
Varsayılan olarak, splash ekranı ile onboarding arasında onboarding tam olarak yüklenene kadar yükleme ekranı görünür. Ancak geçişi daha pürüzsüz hale getirmek istiyorsanız, bunu özelleştirebilir; splash ekranını uzatabilir ya da başka bir şey gösterebilirsiniz.
Bunun için bir placeholder tanımlayın (onboarding yüklenirken tam olarak ne gösterileceğini belirleyin). Bir placeholder tanımlarsanız, onboarding arka planda yüklenir ve hazır olduğunda otomatik olarak gösterilir.
```swift showLineNumbers
extension YourOnboardingManagerClass: AdaptyOnboardingControllerDelegate {
func onboardingsControllerLoadingPlaceholder(
_ controller: AdaptyOnboardingController
) -> UIView? {
// instantiate and return the UIView which will be presented while onboarding is being loaded
}
}
```
```swift showLineNumbers
AdaptyOnboardingView(
configuration: configuration,
placeholder: {
// define your placeholder view, which will be presented while onboarding is being loaded
},
// the rest of the implementation
)
```
## Onboarding'lerdeki bağlantıların nasıl açılacağını özelleştirme \{#customize-how-links-open-in-onboardings\}
:::important
Onboarding'lerdeki bağlantıların nasıl açılacağını özelleştirme özelliği Adapty SDK v3.15.1 sürümünden itibaren desteklenmektedir.
:::
Varsayılan olarak, onboarding'lerdeki bağlantılar uygulama içi bir tarayıcıda açılır. Bu, kullanıcıların uygulama değiştirmeden web sayfalarını görüntüleyebilmesini sağlayarak kesintisiz bir kullanıcı deneyimi sunar.
Bağlantıların bunun yerine harici bir tarayıcıda açılmasını tercih ederseniz, `externalUrlsPresentation` parametresini `.externalBrowser` olarak ayarlayarak bu davranışı özelleştirebilirsiniz:
```swift showLineNumbers
let configuration = try AdaptyUI.getOnboardingConfiguration(
forOnboarding: onboarding,
externalUrlsPresentation: .externalBrowser // default – .inAppBrowser
)
```
---
# File: ios-handling-onboarding-events
---
---
title: "iOS SDK'da onboarding olaylarını yönetme"
description: "Adapty kullanarak iOS'ta onboarding ile ilgili olayları yönetin."
---
:::tip
**SDK v4'ten itibaren**, onboarding'lere daha güçlü bir alternatif olarak [flow'lar](get-pb-paywalls) oluşturabilirsiniz. WebView içinde çalışan onboarding'lerin aksine, flow'lar cihazda yerel olarak render edilir — bu sayede daha akıcı animasyonlar, tutarlı bir iOS görünümü, daha hızlı yükleme süreleri ve WebView çalışma zamanı bağımlılığı ortadan kalkar. Başlamak için [Flow'ları ve paywall'ları alma](get-pb-paywalls) ve [Flow'ları ve paywall'ları gösterme](ios-present-paywalls) konularına bakın.
:::
Başlamadan önce şunların sağlandığından emin olun:
1. [Adapty iOS SDK](sdk-installation-ios) 3.8.0 veya daha yeni bir sürümü yüklediniz.
2. [Bir onboarding oluşturdunuz](create-onboarding).
3. Onboarding'i bir [placement](placements)'a eklediniz.
Builder ile yapılandırılan onboarding'ler, uygulamanızın yanıt verebileceği olaylar üretir. Bu olaylara nasıl yanıt vereceğinizi aşağıda öğrenebilirsiniz.
Mobil uygulamanızdaki onboarding ekranında gerçekleşen süreçleri kontrol etmek veya izlemek için `AdaptyOnboardingControllerDelegate` metodlarını uygulayın.
## Özel eylemler \{#custom-actions\}
Builder'da bir düğmeye **özel** bir eylem ekleyip bu eyleme bir ID atayabilirsiniz.
Bu ID'yi kodunuzda kullanarak özel bir eylem olarak işleyebilirsiniz. Örneğin, bir kullanıcı **Login** veya **Allow notifications** gibi özel bir düğmeye dokunduğunda, delegate metodu `onboardingController`, `.custom(id:)` durumuyla tetiklenir ve `actionId` parametresi builder'daki **Action ID**'dir. "allowNotifications" gibi kendi ID'lerinizi oluşturabilirsiniz.
```swift showLineNumbers
func onboardingController(_ controller: AdaptyOnboardingController, onCustomAction action: AdaptyOnboardingsCustomAction) {
if action.actionId == "allowNotifications" {
// Request notification permissions
}
}
func onboardingController(_ controller: AdaptyOnboardingController, didFailWithError error: AdaptyUIError) {
// Handle errors
}
```
Olay örneği (Genişletmek için tıklayın)
```json
{
"actionId": "allowNotifications",
"meta": {
"onboardingId": "onboarding_123",
"screenClientId": "profile_screen",
"screenIndex": 0,
"screensTotal": 3
}
}
```
## Onboarding'i kapatma \{#closing-onboarding\}
Bir kullanıcı **Close** eylemi atanmış bir düğmeye dokunduğunda onboarding kapatılmış sayılır.
:::important
Kullanıcı onboarding'i kapattığında ne olacağını siz yönetmeniz gerektiğini unutmayın. Örneğin, onboarding'in kendisini görüntülemeyi durdurmanız gerekir.
:::
Örneğin:
```swift showLineNumbers
func onboardingController(_ controller: AdaptyOnboardingController, onCloseAction action: AdaptyOnboardingsCloseAction) {
controller.dismiss(animated: true)
}
```
Olay örneği (Genişletmek için tıklayın)
```json
{
"action_id": "close_button",
"meta": {
"onboarding_id": "onboarding_123",
"screen_cid": "final_screen",
"screen_index": 3,
"total_screens": 4
}
}
```
## Paywall açma \{#opening-a-paywall\}
:::tip
Onboarding içinde bir paywall açmak istiyorsanız bu eventi işleyin. Paywall kapandıktan sonra açmak istiyorsanız daha kolay bir yol var: [`AdaptyOnboardingsCloseAction`](#closing-onboarding) eventini işleyin ve event verisine dayanmadan paywall'ı açın.
:::
Onboarding'lerde paywall'larla çalışmanın en sorunsuz yolu, action ID'yi bir paywall placement ID'siyle eşit yapmaktır. Bu sayede `AdaptyOnboardingsOpenPaywallAction` sonrasında placement ID'yi kullanarak paywall'ı hemen alıp açabilirsiniz.
Ekranda aynı anda yalnızca bir görünümün (paywall veya onboarding) görüntülenebileceğini unutmayın. Bir onboarding'in üzerine paywall sunarsanız arka plandaki onboarding'i programatik olarak kontrol edemezsiniz. Onboarding'i kapatmaya çalışmak bunun yerine paywall'u kapatır ve onboarding görünür kalır. Bunu önlemek için paywall'u sunmadan önce her zaman onboarding görünümünü kapatın.
```swift showLineNumbers
func onboardingController(_ controller: AdaptyOnboardingController, onPaywallAction action: AdaptyOnboardingsOpenPaywallAction) {
// Dismiss onboarding before presenting the flow
controller.dismiss(animated: true) {
Task {
do {
// Get the flow using the placement ID from the action
let flow = try await Adapty.getFlow(placementId: action.actionId)
// Get the flow configuration
let flowConfiguration = try await AdaptyUI.getFlowConfiguration(
forFlow: flow
)
// Create and present the flow controller
let flowController = try AdaptyUI.flowController(
with: flowConfiguration,
delegate: self
)
// Present the flow from the root view controller
if let rootVC = UIApplication.shared.windows.first?.rootViewController {
rootVC.present(flowController, animated: true)
}
} catch {
// Handle any errors that occur during flow loading
print("Failed to present flow: \(error)")
}
}
}
}
```
Olay örneği (Genişletmek için tıklayın)
```json
{
"action_id": "premium_offer_1",
"meta": {
"onboarding_id": "onboarding_123",
"screen_cid": "pricing_screen",
"screen_index": 2,
"total_screens": 4
}
}
```
## Onboarding yüklemesini tamamlama \{#finishing-loading-onboarding\}
Bir onboarding yüklemeyi tamamladığında bu metod çağrılır:
```swift showLineNumbers
func onboardingController(_ controller: AdaptyOnboardingController, didFinishLoading action: OnboardingsDidFinishLoadingAction) {
// Handle loading completion
}
```
Olay örneği (Genişletmek için tıklayın)
```json
{
"meta": {
"onboarding_id": "onboarding_123",
"screen_cid": "welcome_screen",
"screen_index": 0,
"total_screens": 4
}
}
```
## Navigasyonu izleme \{#tracking-navigation\}
`onAnalyticsEvent` metodu, onboarding akışı sırasında çeşitli analitik olaylar gerçekleştiğinde çağrılır.
`event` nesnesi aşağıdaki türlerden biri olabilir:
|Tür | Açıklama |
|------------|-------------|
| `onboardingStarted` | Onboarding yüklendiğinde |
| `screenPresented` | Herhangi bir ekran gösterildiğinde |
| `screenCompleted` | Bir ekran tamamlandığında. İsteğe bağlı `elementId` (tamamlanan öğenin tanımlayıcısı) ve isteğe bağlı `reply` (kullanıcıdan gelen yanıt) içerir. Kullanıcılar ekrandan çıkmak için herhangi bir eylem gerçekleştirdiğinde tetiklenir. |
| `secondScreenPresented` | İkinci ekran gösterildiğinde |
| `userEmailCollected` | Kullanıcının e-postası giriş alanı üzerinden toplandığında tetiklenir |
| `onboardingCompleted` | Kullanıcı `final` ID'sine sahip bir ekrana ulaştığında tetiklenir. Bu olaya ihtiyacınız varsa [son ekrana `final` ID'sini atayın](design-onboarding). |
| `unknown` | Tanınmayan herhangi bir olay türü için. `name` (bilinmeyen olayın adı) ve `meta` (ek metadata) içerir |
Her olay şu alanları içeren `meta` bilgisi barındırır:
| Alan | Açıklama |
|------------|-------------|
| `onboardingId` | Onboarding akışının benzersiz tanımlayıcısı |
| `screenClientId` | Mevcut ekranın tanımlayıcısı |
| `screenIndex` | Akıştaki mevcut ekranın konumu |
| `screensTotal` | Akıştaki toplam ekran sayısı |
Analitik olayları izleme amacıyla nasıl kullanabileceğinize dair bir örnek:
```swift
func onboardingController(_ controller: AdaptyOnboardingController, onAnalyticsEvent event: AdaptyOnboardingsAnalyticsEvent) {
switch event {
case .onboardingStarted(let meta):
// Track onboarding start
trackEvent("onboarding_started", meta: meta)
case .screenPresented(let meta):
// Track screen presentation
trackEvent("screen_presented", meta: meta)
case .screenCompleted(let meta, let elementId, let reply):
// Track screen completion with user response
trackEvent("screen_completed", meta: meta, elementId: elementId, reply: reply)
case .onboardingCompleted(let meta):
// Track successful onboarding completion
trackEvent("onboarding_completed", meta: meta)
case .unknown(let meta, let name):
// Handle unknown events
trackEvent(name, meta: meta)
// Handle other cases as needed
}
}
```
Olay örnekleri (Genişletmek için tıklayın)
```javascript
// onboardingStarted
{
"name": "onboarding_started",
"meta": {
"onboarding_id": "onboarding_123",
"screen_cid": "welcome_screen",
"screen_index": 0,
"total_screens": 4
}
}
// screenPresented
{
"name": "screen_presented",
"meta": {
"onboarding_id": "onboarding_123",
"screen_cid": "interests_screen",
"screen_index": 2,
"total_screens": 4
}
}
// screenCompleted
{
"name": "screen_completed",
"meta": {
"onboarding_id": "onboarding_123",
"screen_cid": "profile_screen",
"screen_index": 1,
"total_screens": 4
},
"params": {
"element_id": "profile_form",
"reply": "success"
}
}
// secondScreenPresented
{
"name": "second_screen_presented",
"meta": {
"onboarding_id": "onboarding_123",
"screen_cid": "profile_screen",
"screen_index": 1,
"total_screens": 4
}
}
// userEmailCollected
{
"name": "user_email_collected",
"meta": {
"onboarding_id": "onboarding_123",
"screen_cid": "profile_screen",
"screen_index": 1,
"total_screens": 4
}
}
// onboardingCompleted
{
"name": "onboarding_completed",
"meta": {
"onboarding_id": "onboarding_123",
"screen_cid": "final_screen",
"screen_index": 3,
"total_screens": 4
}
}
```
---
# File: ios-onboarding-input
---
---
title: "iOS SDK'da onboarding verilerini işleme"
description: "Adapty SDK ile iOS uygulamanızdaki onboarding verilerini kaydedin ve kullanın."
---
:::tip
**SDK v4'ten itibaren**, onboarding'lere daha güçlü bir alternatif olarak [flow'lar](get-pb-paywalls) oluşturabilirsiniz. Onboarding'ler WebView içinde çalışırken flow'lar cihazda native olarak render edilir; bu sayede daha akıcı animasyonlar, tutarlı bir iOS görünümü, daha hızlı yükleme süreleri ve WebView bağımlılığı olmadan çalışma imkânı sunar. Başlamak için [Flow ve paywall'ları alma](get-pb-paywalls) ve [Flow ve paywall'ları gösterme](ios-present-paywalls) sayfalarına bakın.
:::
Kullanıcılarınız bir sınav sorusunu yanıtladığında veya bir giriş alanına veri girdiğinde `onStateUpdatedAction` metodu çağrılır. Alan türünü kodunuzda kaydedebilir veya işleyebilirsiniz.
Örneğin:
```swift showLineNumbers
func onboardingController(_ controller: AdaptyOnboardingController, onStateUpdatedAction action: AdaptyOnboardingsStateUpdatedAction) {
// Store user preferences or responses
switch action.params {
case .select(let params):
// Handle single selection
case .multiSelect(let params):
// Handle multiple selections
case .input(let params):
// Handle text input
case .datePicker(let params):
// Handle date selection
}
}
```
`action` nesnesi şunları içerir:
| Parametre | Açıklama |
|----------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `elementId` | Giriş öğesi için benzersiz bir tanımlayıcı. Soruları yanıtlarla ilişkilendirmek için kullanabilirsiniz. |
| `params` | Tür ve değer özelliklerini içeren kullanıcının giriş verisi nesnesi. |
| `params.type` | Giriş öğesinin türü. Şunlardan biri olabilir: • `"select"` - Seçeneklerden tek seçim • `"multiSelect"` - Seçeneklerden çoklu seçim • `"input"` - Metin giriş alanı • `"datePicker"` - Tarih seçimi |
| `params.value` | Kullanıcının seçtiği veya girdiği değer(ler). Yapısı türe göre değişir: • `select`: `id`, `value`, `label` içeren nesne • `multiSelect`: `id`, `value`, `label` içeren nesnelerden oluşan dizi • `input`: `type`, `value` içeren nesne • `datePicker`: `day`, `month`, `year` içeren nesne |
Kaydedilen veri örnekleri (uygulamanızda farklılık gösterebilir)
```javascript
// Example of a saved select action
{
"elementId": "preference_selector",
"meta": {
"onboardingId": "onboarding_123",
"screenClientId": "preferences_screen",
"screenIndex": 1,
"screensTotal": 3
},
"params": {
"type": "select",
"value": {
"id": "option_1",
"value": "premium",
"label": "Premium Plan"
}
}
}
// Example of a saved multi-select action
{
"elementId": "interests_selector",
"meta": {
"onboardingId": "onboarding_123",
"screenClientId": "interests_screen",
"screenIndex": 2,
"screensTotal": 3
},
"params": {
"type": "multiSelect",
"value": [
{
"id": "interest_1",
"value": "sports",
"label": "Sports"
},
{
"id": "interest_2",
"value": "music",
"label": "Music"
}
]
}
}
// Example of a saved input action
{
"elementId": "name_input",
"meta": {
"onboardingId": "onboarding_123",
"screenClientId": "profile_screen",
"screenIndex": 0,
"screensTotal": 3
},
"params": {
"type": "input",
"value": {
"type": "text",
"value": "John Doe"
}
}
}
// Example of a saved date picker action
{
"elementId": "birthday_picker",
"meta": {
"onboardingId": "onboarding_123",
"screenClientId": "profile_screen",
"screenIndex": 0,
"screensTotal": 3
},
"params": {
"type": "datePicker",
"value": {
"day": 15,
"month": 6,
"year": 1990
}
}
}
```
## Kullanım senaryoları \{#use-cases\}
### Kullanıcı profillerini verilerle zenginleştirme \{#enrich-user-profiles-with-data\}
Giriş verilerini kullanıcı profiliyle hemen ilişkilendirmek ve aynı bilgiyi iki kez sormaktan kaçınmak istiyorsanız, aksiyonu işlerken [kullanıcı profilini](setting-user-attributes) giriş verileriyle güncellemeniz gerekir.
Örneğin, kullanıcılardan `name` ID'li metin alanına adlarını girmelerini istiyorsunuz ve bu alanın değerini kullanıcının adı olarak kaydetmek istiyorsunuz. Ayrıca `email` alanına e-posta adreslerini girmelerini de istiyorsunuz. Uygulama kodunuzda bu şöyle görünebilir:
```swift showLineNumbers
func onboardingController(_ controller: AdaptyOnboardingController, onStateUpdatedAction action: AdaptyOnboardingsStateUpdatedAction) {
// Store user preferences or responses
switch action.params {
case .input(let params):
// Handle text input
let builder = AdaptyProfileParameters.Builder()
// Map elementId to appropriate profile field
switch action.elementId {
case "name":
builder.with(firstName: params.value.value)
case "email":
builder.with(email: params.value.value)
default:
break
}
// Delegate methods are synchronous; kick off the async update in a Task.
Task {
do {
try await Adapty.updateProfile(params: builder.build())
} catch {
// handle the error
}
}
default:
break
}
}
```
### Yanıtlara göre paywallları özelleştirme \{#customize-paywalls-based-on-answers\}
Onboardinglardaki testleri kullanarak, kullanıcıların onboarding'i tamamlamasının ardından gösterdiğiniz paywallları da özelleştirebilirsiniz.
Örneğin, kullanıcılara spor deneyimlerini sorabilir ve farklı kullanıcı gruplarına farklı CTA'lar ve ürünler gösterebilirsiniz.
1. Onboarding oluşturucuya [bir test ekleyin](onboarding-quizzes) ve seçeneklere anlamlı ID'ler atayın.
2. Test yanıtlarını ID'lerine göre işleyin ve kullanıcılar için [özel nitelikler belirleyin](setting-user-attributes).
```swift showLineNumbers
func onboardingController(_ controller: AdaptyOnboardingController, onStateUpdatedAction action: AdaptyOnboardingsStateUpdatedAction) {
// Handle quiz responses and set custom attributes
switch action.params {
case .select(let params):
// Handle quiz selection
let builder = AdaptyProfileParameters.Builder()
// Map quiz responses to custom attributes
switch action.elementId {
case "experience":
// Set custom attribute 'experience' with the selected value (beginner, amateur, pro)
try? builder.with(customAttribute: params.value.value, forKey: "experience")
default:
break
}
// Delegate methods are synchronous; kick off the async update in a Task.
Task {
do {
try await Adapty.updateProfile(params: builder.build())
} catch {
// handle the error
}
}
default:
break
}
}
```
3. Her özel nitelik değeri için [segment oluşturun](segments).
4. Bir [placement](placements) oluşturun ve oluşturduğunuz her segment için [kitle](audience) ekleyin.
5. Uygulama kodunuzda placement için [bir paywall görüntüleyin](ios-paywalls). Onboarding'inizde paywall açan bir buton varsa, paywall kodunu [bu butonun aksiyonuna verilen yanıt](ios-handling-onboarding-events#opening-a-paywall) olarak uygulayın.
---
# File: ios-sdk-call-order
---
---
title: "iOS SDK'da çağrı sırası"
description: "Adapty SDK metodlarını doğru sırayla çağırarak premium erişim kaybını, eksik attribution'ı ve aralıklı #2002 hatalarını önleyin."
---
`Adapty.activate()` tamamlanmadan başka hiçbir Adapty SDK metodunu çağırmamalısınız. Bu metod sonuçlanmadan SDK'nın herhangi bir durumu yoktur. `activate()` ile eş zamanlı ya da öncesinde yapılan her çağrı [`#2002 notActivated`](ios-sdk-error-handling#network-errors) hatasıyla başarısız olur.
Uygulamanız kullanıcıları doğruluyorsa ve başlatma sonrasında bir müşteri kullanıcı kimliği topluyorsanız, bu noktada `Adapty.identify()` çağrısı yapın. `identify` tamamlanana kadar kullanıcı eylemine bağlı metodları çağırmayın. Bu çağrıyla yarışan işlemler ya [`#3006 profileWasChanged`](ios-sdk-error-handling#general-errors) hatasıyla başarısız olur ya da aktivasyon sırasında oluşturulan anonim profile düşer. Bu durumda attribution, `appsflyer_id` gibi MMP kimlik bilgileri ve kurulum sahipliği her zaman tanımlanan profile aktarılmaz. Uygulamanız kullanıcıları doğrulamıyorsa `identify` çağrısını atlayın ve anonim profille çalışmaya devam edin.
MMP ve analitik SDK'ları (AppsFlyer, Adjust, Branch, PostHog) aynı kurala tabidir. `Adapty.activate` çağrısından önce bunları başlatın ve UID callback'lerini bekleyin. Aksi takdirde MMP ID'si kısa ömürlü anonim bir profile düşer ve tanımlı profile her zaman aktarılamaz. AppsFlyer'a özgü ayrıntılar için bkz. [AppsFlyer](appsflyer).
## Doğru sıra \{#the-correct-order\}
Hangi adımları izleyeceğiniz iki şeye bağlıdır: müşteri kullanıcı kimliğini ne zaman öğrendiğiniz ve MMP ya da analitik SDK kullanıp kullanmadığınız.
- **2. ve 5. adımlar**: Her uygulama için zorunludur. SDK'yı etkinleştirin, ardından SDK metotlarını çağırın.
- **1. ve 3. adımlar**: Yalnızca bir MMP veya analitik SDK (AppsFlyer, Adjust, Branch, PostHog) entegre ediyorsanız gereklidir.
- **4. adım**: Yalnızca uygulamanız kullanıcıların kimliğini doğruluyorsa ve müşteri kullanıcı kimliğini başlatma sonrasında topluyorsa gereklidir.
Uygulama başlatıldığında müşteri kullanıcı kimliğine sahipseniz, doğrudan `activate()` fonksiyonuna aktarın (adım 2a). Bu yöntem hiçbir zaman anonim profil oluşturmaz, dolayısıyla 4. adım gereksizdir.
| Adım | Çağrı | Ne Zaman | Notlar |
|------|---------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------|
| 1 | MMP veya analitik SDK'nızı başlatın (AppsFlyer, Adjust, PostHog, Branch) | Uygulama başlatılırken, ilk önce | MMP'nin UID geri çağırmasını bekleyin, örneğin `getAppsFlyerUID`. |
| 2a | `Adapty.activate(with: config)` — config üzerinde `customerUserId` ayarlanmış | Uygulama başlatılırken, 1. adımdan sonra, customer user ID'niz varsa | Önerilir. Anonim profil hiçbir zaman oluşturulmaz. |
| 2b | `Adapty.activate(with: config)` — `customerUserId` olmadan | Uygulama başlatılırken, 1. adımdan sonra, customer user ID'niz yoksa (veya hiç toplanmıyorsa) | Adapty anonim bir profil oluşturur. |
| 3 | Her MMP için `Adapty.setIntegrationIdentifier(...)` | 2. adımdan sonra, herhangi bir kullanıcı eylemi çağrısından önce | MMP ID'lerinin doğru profile düşmesi için zorunludur. |
| 4 | `try await Adapty.identify("YOUR_USER_ID")` | 3. adımdan sonra (veya MMP yoksa 2. adımdan sonra), 5. adımdan önce — yalnızca kimlik doğrulama ile 2b yolunda | Her zaman `await` kullanın. `identify` sırasında eş zamanlı çağrılar `#3006 profileWasChanged` hatasına yol açar. |
| 5 | `getPaywall`, `getPaywallProducts`, `restorePurchases`, `makePurchase`, `updateAttribution`, `updateProfile` | `identify` çağırıyorsanız 4. adımdan sonra; aksi takdirde 3. adımdan sonra (veya MMP yoksa 2. adımdan sonra) | Bu çağrılar kararlı bir profil gerektirir. |
:::important
Bu adımları atlamak; geri dönen kullanıcıların premium erişimini kaybetmesine, profillerde eksik `appsflyer_id` bilgisine ve yanlış kitleye karşı döndürülen paywalls'a yol açar.
:::
## Web2app ve web-funnel kurulumları \{#web2app-and-web-funnel-installs\}
Kullanıcılar bir web ödeme sayfasından (Stripe, Paddle, FunnelFox) satın alıp ardından uygulamayı yüklerse, cihazın ilk `activate()` çağrısı yeni bir anonim profil oluşturur. Bu profil, web profiliyle ilişkilendirilmez. Uygulama başlatılmadan önce kullanıcı kimliğini (auth akışından veya install referrer'dan) çözümleyebiliyorsanız, doğrudan `activate()` içine geçirin. Aksi takdirde web satın alımı, `identify("YOUR_USER_ID")` ve ardından `restorePurchases` çağrısı yapılana kadar cihazda görünmez.
Her web ödeme sayfasıyla gönderilecek metadata için şuralara bakın:
- [Stripe](stripe)
- [Paddle](paddle)
---
# File: ios-optimize-paywall-fetching
---
---
title: "iOS SDK'da paywall getirme işlemini optimize etme"
description: "Adapty paywall'larını güvenilir şekilde getirin: iOS için zamanlama, önbellekleme ve yedek desenleri."
---
iOS'ta güvenilir bir paywall getirme işlemi üç şeyi başarır: hızlı render eder, kitleyeye hedeflenmiş paywall'ı döndürür ve ağ yavaş olduğunda sorunsuz yedek sunar. Aşağıdaki kurallar bunu sağlamak için zamanlama, önbellekleme ve yedek desenlerini kapsar.
:::tip
Bu kurallar, `Adapty.activate()` ve `Adapty.identify()` işlemlerinin tamamlandığını varsayar. Bkz. [iOS SDK'da çağrı sırası](ios-sdk-call-order).
:::
## Kurallar ve tuzaklar \{#rules-and-pitfalls\}
| Bunu yap | Bunu yapma | Neden |
|---|---|---|
| Göstermek üzere olduğunuz placement'ı çekin. | Başlangıçta tüm placement'ları eş zamanlı olarak önceden çekin. | Toplu önceden çekme ana thread'i bloke eder ve burst sırasında siyah ekrana yol açar. |
| `getPaywall` işlevini attribution'ın çözülmesine fırsat tanıdıktan sonra çekin — örneğin `activate` işlevinden 1–2 saniye sonra ya da `onProfileUpdate` tetiklendikten sonra. | `getPaywall` işlevini `App.init()` sırasında çağırın. | Attribution henüz gelmemiştir. Paywall, varsayılan kitleye göre çözümlenir ve segmentleri ile ASA kişiselleştirmesini sessizce atlar. |
| Her placement için bir `loadTimeout` belirleyin ve bir [yedek paywall](fallback-paywalls) yapılandırın. | `getPaywall` işleminin bitmesini süresiz bekleyin. | Zaman aşımı olmadan, bağlantısı zayıf olan kullanıcılar ağ çözülene kadar boş bir ekran görür — ya da uygulamayı kapatır. |
`fetchPolicy` ve `loadTimeout` parametre referansı için [Paywall ve ürünleri getirme](fetch-paywalls-and-products) sayfasına, doğru placement'ı seçmek için ise [Placement'lar](placements) sayfasına bakın.
## Bağlantı sorunları için ayarlar \{#tune-for-poor-connectivity\}
Sürekli zayıf bağlantının yaşandığı pazarlar için (kırsal alanlar, toplu taşıma, yönlendirme sorunlarından etkilenen bölgeler):
- İlk fetch dışında her fetch işleminde `fetchPolicy: .returnCacheDataElseLoad` kullanın.
- Adapty Kontrol Paneli'ndeki her placement için bir [yedek paywall](fallback-paywalls) yapılandırın.
- `loadTimeout` değerini 3–5 saniye olarak ayarlayın ve zaman aşımı gerçekleştiğinde yedek paywalla geçin.
- Paywall gösterimini `getProfile()` sonucuna bağlamayın. `getPaywall` işlemini bağımsız olarak çağırın; böylece yavaş bir profil yüklemesi arayüzü bloke etmez.
---
# File: ios-show-aa-targeted-paywall
---
---
title: "iOS SDK'da ilk başlatmada AA hedefli paywall gösterme"
description: "AdaptyProfile.appliedAttributionSources kullanarak iOS'ta paywall istemeden önce Apple Ads attribution'ını bekleyin."
---
Apple Ads (AA) attribution, `Adapty.activate()` çağrısından sonra asenkron olarak gelir. `getPaywall` fonksiyonunu erken çağırırsanız, attribution henüz gelmemiş olabilir ve Adapty, placement'ı varsayılan kitle üzerinden çözümleyerek AA segmentine göre ayarlanmış paywallları atlayabilir. `AdaptyProfile.appliedAttributionSources`, uygulamanın AA attribution'ının profile uygulanıp uygulanmadığını tespit etmesini sağlar; böylece paywall isteği, AA segmentasyonunun doğru şekilde çözümleneceği ana kadar bekletilebilir.
## Başlamadan önce \{#before-you-start\}
İhtiyacınız olanlar:
- Adapty iOS SDK **3.17.1** veya üzeri.
- Uygulamanız için Adapty'de Apple Ads yapılandırılmış olması. Bkz. [Apple Ads](apple-search-ads).
## Nasıl çalışır \{#how-it-works\}
`Adapty.activate()` çağrısının ardından SDK, arka planda Apple'dan Apple Ads attribution bilgisini talep eder ve sonucu Adapty'nin backend'ine iletir. AA, profil için aktif attribution kaynağı haline geldiğinde SDK, `appliedAttributionSources` dizisinde `.appleAds` içeren güncellenmiş bir `AdaptyProfile` döndürür.
Boş bir dizi şu anlara gelebilir:
- Bu profil için Apple Ads attribution henüz işlenmemiş olabilir.
- Hiç attribution gelmemiş olabilir.
Boş bir dizi ile bile `getPaywall` çağrısı güvenlidir — Adapty, isteği mevcut profil durumuna uyan kitleye göre (genellikle varsayılan kitle) çözümler.
:::important
Bekleme yalnızca **ilk başlatma** için geçerlidir. Apple Ads attribution kaydedildikten sonra profilde kalıcı olarak saklanır. Sonraki her başlatmada önbelleğe alınmış profil zaten `appliedAttributionSources` içinde `.appleAds` değerini taşır, `didLoadLatestProfile` bu değerle anında tetiklenir ve `getPaywall` herhangi bir gecikme olmadan Apple Ads segmentine uygun paywall'ı döndürür.
:::
## Uygulama \{#implementation\}
İlk açılışta profilde `.appleAds` değerini izleyin ve sert bir zaman aşımı uygulayın — Apple Ads attribution hiç gelmese bile, o kullanıcıların yine de bir paywall görmesi gerekir.
1. **SDK'yı etkinleştirin.** Bkz. [iOS SDK'yı yükle ve yapılandır](sdk-installation-ios).
2. **Profil güncellemelerini dinleyin:** `AdaptyDelegate`'e uyum sağlayarak `didLoadLatestProfile`'ı uygulayın. Delegate'i henüz ayarlamadıysanız bkz. [Abonelik güncellemelerini dinle](ios-check-subscription-status#listen-to-subscription-updates).
3. **`appliedAttributionSources` içinde `.appleAds` çıkıp çıkmadığını takip edin.** Göründüğünde paywall'ı isteyin — Adapty, AA segmentine göre belirlenmiş varyantı döndürecektir:
```swift
extension : AdaptyDelegate {
nonisolated func didLoadLatestProfile(_ profile: AdaptyProfile) {
if profile.appliedAttributionSources.contains(where: { $0 == .appleAds }) {
// load paywall via Adapty.getPaywall(placementId:)
}
}
}
```
4. **Abonelikle paralel olarak 3–5 saniyelik bir zamanlayıcı başlatın.** Zamanlayıcı `.appleAds` görünmeden tetiklenirse, yine de paywallı isteyin:
Hangi yol önce tetiklenirse o ywall'ı yüklemeli; diğer yol atlanmalıdır. Paywall'ın iki kez getirilmemesi için tek bir durum bayrağı (örneğin `hasLoadedPaywall`) kullanarak yinelenenleri ortadan kaldırın. Ağ isteği başarısız olduğunda kullanıcının askıda kalmaması için placement'a bir [yedek paywall](fallback-paywalls) yapılandırın.
## Eksiksiz örnek \{#complete-example\}
Aşağıdaki implementasyon, attribution ile bir zaman aşımını yarıştırır, varsayılan kitle paywallını paralel olarak önceden çeker ve uygun olan paywallı döndürür. Çağıran taraf yalnızca tek bir async fonksiyonu bekler; çağrı noktasında yönetilmesi gereken delegate veya durum bayrağı yoktur.
`ProfileObserver`, `AdaptyDelegate`'ten gelen profil güncellemelerini yayınlayan yeniden kullanılabilir bir singleton'dır. `PaywallLoader.getPaywallOrDefault` ise yarışı yapılandırılmış eşzamanlılık `TaskGroup` kullanarak yürütür:
- Attribution `timeout` süresi içinde gelirse, `getPaywall(placementId:)` aracılığıyla segmentlere ayrılmış paywall döndürülür.
- `timeout` süresi önce dolarsa, `getPaywallForDefaultAudience(placementId:)` aracılığıyla önceden yüklenmiş varsayılan kitle paywall'u döndürülür.
```swift title="PaywallLoader.swift"
/// Attribution uygulanmasına bağlı bir paywallın nasıl getirileceğini gösterir;
/// attribution zamanında gelmezse varsayılan kitle paywallına geri düşer.
///
/// Durumsuz ve bağımsızdır: her çağrı kendi varsayılan kitle ön getirme işlemini
/// başlatır ve bunu attribution + segmentli getirme ile yarıştırır.
enum PaywallLoader {
static func getPaywallOrDefault(
placementId: String,
timeout: TimeInterval
) async throws -> AdaptyPaywall {
struct TimedOut: Error {}
// Varsayılan kitle isteğini hemen başlat; böylece yüklemek için tam
// `timeout` süresi olur. Başarı durumunda iptal edilir, zaman aşımında
// sonucu beklenir — hiçbir zaman yinelenen ağ çağrısı yapılmaz.
let defaultPaywallTask = Task {
try await Adapty.getPaywallForDefaultAudience(placementId: placementId)
}
do {
// İki alt görevi yarıştır: hangisi önce biterse o kazanır.
let result = try await withThrowingTaskGroup(of: AdaptyPaywall.self) { group in
// 1. Attribution'ı bekle, ardından Adapty'den segmentli paywallı iste.
group.addTask {
await waitForAttribution()
return try await Adapty.getPaywall(placementId: placementId)
}
// 2. Zaman bombası: `timeout` saniye sonra `TimedOut` fırlatır.
group.addTask {
try await Task.sleep(nanoseconds: UInt64(timeout * 1_000_000_000))
throw TimedOut()
}
guard let value = try await group.next() else { throw CancellationError() }
group.cancelAll() // Kaybedeni durdur (uyuyan görev veya attribution bekleyen).
return value
}
// Segmentli paywall kazandı — varsayılan kitle ön getirme artık gerekli değil.
defaultPaywallTask.cancel()
return result
} catch is TimedOut {
// Attribution zamanında uygulanamadı — önceden yüklenen varsayılanı döndür
// (zaten tamamlandıysa anında, değilse devam eden isteği bekle).
return try await defaultPaywallTask.value
}
}
/// İstenen attribution kaynağına sahip bir profil gözlemlenene kadar askıya alır.
/// `@Published.values`, abonelikte mevcut profili hemen yayımlar; bu nedenle
/// attribution zaten uygulanmışsa ilk iterasyonda geri döner.
@MainActor
private static func waitForAttribution() async {
for await profile in ProfileObserver.shared.$profile.values {
if profile?.appliedAttributionSources.contains(.appleAds) == true { return }
}
}
}
@MainActor
final class ProfileObserver: AdaptyDelegate {
static let shared = ProfileObserver()
@Published private(set) var profile: AdaptyProfile?
nonisolated func didLoadLatestProfile(_ profile: AdaptyProfile) {
Task { @MainActor [weak self] in
self?.profile = profile
}
}
}
```
`Adapty.activate()` tamamlandıktan sonra `ProfileObserver`'ı `AdaptyDelegate`'e bir kez bağlayın:
```swift
Adapty.delegate = ProfileObserver.shared
```
Splash ekranından çağırın:
```swift
do {
let paywall = try await PaywallLoader.getPaywallOrDefault(
placementId: "YOUR_PLACEMENT_ID",
timeout: 5
)
// paywallı göster
} catch {
// hatayı yönet veya yedek paywall göster
}
```
Uygulamanız başka amaçlar için zaten bir `AdaptyDelegate` kullanıyorsa (örneğin, [abonelik güncellemelerini dinlemek](ios-check-subscription-status#listen-to-subscription-updates) için), `Adapty.delegate = ProfileObserver.shared` yapmak yerine mevcut delegate'inizden `didLoadLatestProfile`'ı `ProfileObserver.shared`'a iletin.
---
# File: ios-test
---
---
title: "iOS SDK'da Test & Yayınlama"
description: "Adapty ile iOS uygulamanızdaki abonelik durumunu nasıl kontrol edeceğinizi öğrenin."
---
Adapty SDK'yı iOS uygulamanıza zaten entegre ettiyseniz, her şeyin doğru kurulduğunu ve satın almaların beklendiği gibi çalıştığını test etmek isteyeceksiniz. Bu, hem SDK entegrasyonunu hem de gerçek satın alma işlemini test etmeyi kapsar.
## Uygulamanızı test edin \{#test-your-app\}
Sandbox testi ve TestFlight doğrulaması dahil olmak üzere uygulama içi satın almalarınızı kapsamlı şekilde test etmek için [test kılavuzumuza](test-purchases-in-sandbox) göz atın.
## Yayına hazırlanın \{#prepare-for-release\}
Uygulamanızı mağazaya göndermeden önce, aşağıdakileri doğrulamak için [Yayın kontrol listesini](release-checklist) takip edin:
- Mağaza bağlantısı ve sunucu bildirimleri yapılandırıldı
- Satın almalar tamamlanıyor ve Adapty'ye raporlanıyor
- Erişim doğru şekilde açılıyor ve geri yükleniyor
- Gizlilik ve inceleme gereksinimleri karşılandı
---
# File: InvalidProductIdentifiers
---
---
title: "Code-1000 noProductIDsFound hatası için çözüm"
description: "Adapty'de abonelikleri yönetirken geçersiz ürün tanımlayıcısı hatalarını çözün."
---
1000 kodlu `noProductIDsFound` hatası, paywall'da istediğiniz ürünlerin App Store'da listelenmiş olmasına rağmen satın alma için kullanılamadığını gösterir. Bu hata zaman zaman `InvalidProductIdentifiers` uyarısıyla birlikte gelebilir. Uyarı hatasız tek başına görünüyorsa görmezden gelebilirsiniz.
`noProductIDsFound` hatasıyla karşılaşıyorsanız sorunu çözmek için şu adımları izleyin:
## Adım 1. Bundle ID'yi kontrol edin \{#step-2-check-bundle-id\}
1. [App Store Connect](https://appstoreconnect.apple.com/apps)'i açın. Uygulamanızı seçin ve **General** → **App Information** bölümüne gidin.
2. **General Information** alt bölümündeki **Bundle ID**'yi kopyalayın.
3. Adapty üst menüsünden [**App settings** -> **iOS SDK** sekmesini](https://app.adapty.io/settings/ios-sdk) açın ve kopyaladığınız değeri **Bundle ID** alanına yapıştırın.
4. App Store Connect'teki **App information** sayfasına geri dönün ve oradan **Apple ID**'yi kopyalayın.
5. Adapty kontrol panelindeki [**App settings** -> **iOS SDK**](https://app.adapty.io/settings/ios-sdk) sayfasında, ID'yi **Apple app ID** alanına yapıştırın.
## Adım 2. Ürünleri kontrol edin
1. **App Store Connect**'e gidin ve sol menüden [**Monetization** → **Subscriptions**](https://appstoreconnect.apple.com/apps/6477523342/distribution/subscriptions) bölümüne geçin.
2. Abonelik grubu adına tıklayın. Ürünlerinizi **Subscriptions** bölümünde listelenmiş şekilde göreceksiniz.
3. Test ettiğiniz ürünün **Ready to Submit** olarak işaretlendiğinden emin olun. Değilse [App Store'daki Ürün](app-store-products) sayfasındaki talimatları izleyin.
4. Tablodaki ürün kimliğini Adapty Kontrol Paneli'ndeki [**Products**](https://app.adapty.io/products) sekmesindekiyle karşılaştırın. Kimlikler eşleşmiyorsa ürün kimliğini tablodan kopyalayın ve Adapty Kontrol Paneli'nde bu kimlikle [ürün oluşturun](create-product).
## Adım 3. Ürün kullanılabilirliğini kontrol edin \{#step-4-check-product-availability\}
1. **App Store Connect**'e geri dönün ve aynı **Subscriptions** bölümünü açın.
2. Ürünlerinizi görüntülemek için abonelik grubu adına tıklayın.
3. Test ettiğiniz ürünü seçin.
4. **Availability** bölümüne inin ve gerekli tüm ülke ve bölgelerin listelendiğini doğrulayın.
## Adım 4. Ürün fiyatlarını kontrol edin \{#step-5-check-product-prices\}
1. **App Store Connect**'teki **Monetization** → **Subscriptions** bölümüne tekrar gidin.
2. Abonelik grubu adına tıklayın.
3. Test ettiğiniz ürünü seçin.
4. **Subscription Pricing** bölümüne inin ve **Current Pricing for New Subscribers** kısmını genişletin.
5. Gerekli tüm fiyatların listelendiğinden emin olun.
## Adım 5. Uygulama ücretli durumunu, banka hesabını ve vergi formlarının aktif olduğunu kontrol edin \{#step-5-check-app-paid-status-bank-account-and-tax-forms-are-active\}
1. **[App Store Connect](https://appstoreconnect.apple.com/)** ana sayfasında **Business** seçeneğine tıklayın.
2. Şirket adınızı seçin.
3. Aşağı kaydırın ve **Paid Apps Agreement**, **Bank Account** ile **Tax forms** başlıklarının hepsinin **Active** olarak göründüğünü doğrulayın.
Bu adımları izleyerek `InvalidProductIdentifiers` uyarısını çözebilir ve ürünlerinizi mağazada yayınlayabilirsiniz.
## Adım 6. Ürün takıldıysa yeniden oluşturun \{#step-6-recreate-the-product-if-its-stuck\}
1–5 arası adımların tamamı başarıyla geçebilir — `Approved` durumu, eşleşen Bundle ID, geçerli API anahtarı — yine de SDK `1000 noProductIDsFound` hatası döndürmeye devam edebilir. Bu durumda ürün Apple'ın kayıt sisteminde takılı kalmış olabilir. Apple'ın ürün kayıt sistemi zaman zaman öyle bir duruma girer ki ürün App Store Connect arayüzünde görünür ama StoreKit arama yoluna açık değildir.
Ürünü App Store Connect'ten silin ve aynı ürün kimliğiyle yeniden oluşturun. Yayılmanın tamamlanması için yeniden oluşturmanın ardından 24 saate kadar bekleyin.
---
# File: cantMakePayments
---
---
title: "Code-1003 cantMakePayment hatasının çözümü"
description: "Adapty'de abonelikleri yönetirken ödeme yapılamıyor hatasını çözün."
---
1003 hatası, `cantMakePayments`, bu cihazda uygulama içi satın alımların yapılamayacağını belirtir.
`cantMakePayments` hatasıyla karşılaşıyorsanız, bu genellikle şu nedenlerden biriyle ilgilidir:
- Cihaz kısıtlamaları: Bu hata Adapty ile ilgili değildir. Aşağıdaki çözüm yollarına bakın.
- Observer mode yapılandırması: `makePurchase` metodu ve observer mode aynı anda kullanılamaz. Aşağıdaki bölüme bakın.
## Sorun: Cihaz kısıtlamaları \{#issue-device-restrictions\}
| Sorun | Çözüm |
|------------------------------|------------------------------------------------------------------------------------------------------------------------------|
| Ekran Süresi kısıtlamaları | [Ekran Süresi](https://support.apple.com/en-us/102470) ayarlarında Uygulama İçi Satın Alım kısıtlamalarını devre dışı bırakın |
| Hesap askıya alındı | Hesap sorunlarını çözmek için Apple Destek ile iletişime geçin |
| Bölgesel kısıtlamalar | Desteklenen bir bölgeden App Store hesabı kullanın |
## Sorun: Observer mode ve makePurchase'ı birlikte kullanmak \{#issue-using-both-observer-mode-and-makepurchase\}
Satın alımları yönetmek için `makePurchases` kullanıyorsanız Observer mode'u kullanmanıza gerek yoktur. [Observer mode](observer-vs-full-mode), yalnızca satın alma mantığını kendiniz uyguladığınızda gereklidir.
Dolayısıyla `makePurchase` kullanıyorsanız, SDK etkinleştirme kodundan Observer mode'u etkinleştiren kısmı güvenle kaldırabilirsiniz.
---
# File: migration-to-ios-sdk-v4
---
---
title: "Adapty iOS SDK'yı v4.0'a Geçirin"
description: "Adapty iOS SDK v4.0'a geçiş yapın: paywall API'lerini flow API'leriyle değiştirin; hem Flow Builder hem de Paywall Builder ile uyumludur."
---
Adapty iOS SDK 4.0, flow'ları tanıtır ve paywall API'lerini buna göre yeniden adlandırır. Yeni API'ler hem yeni Flow Builder hem de mevcut Paywall Builder ile çalışır — Adapty Kontrol Paneli tarafında herhangi bir kurulum değişikliği gerekmez.
## Hızlı referans \{#quick-reference\}
| v3 | v4 |
|---|---|
| `Adapty.getPaywall(placementId:locale:)` | `Adapty.getFlow(placementId:)` |
| `AdaptyUI.getPaywallConfiguration(forPaywall:)` | `AdaptyUI.getFlowConfiguration(forFlow:locale:)` |
| `Adapty.getPaywallProducts(paywall:)` | `Adapty.getPaywallProducts(flow:)` |
| `Adapty.logShowPaywall(_:)` | `Adapty.logShowFlow(_:)` |
| `AdaptyPaywallController` | `AdaptyFlowController` |
| `AdaptyPaywallControllerDelegate` | `AdaptyFlowControllerDelegate` |
| `AdaptyUI.paywallController(with:delegate:)` | `AdaptyUI.flowController(with:delegate:)` |
| `.paywall()` (SwiftUI modifier) | `.flow()` |
| `AdaptyPaywallView` | `AdaptyFlowView` |
| `didFailRenderingWith:` / `didFailRendering:` | `didReceiveError:` |
| `didFinishPurchase` (isteğe bağlı, başarıda otomatik kapanır) | `didFinishPurchase` (zorunlu, otomatik kapanma yok) |
| `Adapty_KidsMode` / `AdaptyUI_KidsMode` paket ürünleri | `KidsMode` paket trait'i |
| `Adapty.updateAttribution(_:source:)` (`source: String`) | `Adapty.updateAttribution(_:source:)` (`source: AdaptyAttributionSource`) |
| `Adapty.setIntegrationIdentifier(key:value:)` | `Adapty.setIntegrationIdentifier(_:)` (`AdaptyIntegrationIdentifier`) |
## Minimum iOS sürümü \{#minimum-ios-version\}
Adapty iOS SDK 4.0, minimum deployment target'ı iOS 13.0'dan **iOS 15.0**'a yükseltiyor. Yükseltmeden önce projenizin iOS Deployment Target'ını 15.0 veya üzerine ayarlayın.
## Kurulum: CocoaPods artık desteklenmiyor \{#installation-cocoapods-no-longer-supported\}
Adapty iOS SDK 4.0, CocoaPods desteğini kaldırdı. SDK'yı [Swift Package Manager](sdk-installation-ios#install-adapty-sdk) ile yükleyin.
Projeniz hâlâ CocoaPods kullanıyorsa `Podfile` dosyanızdan `Adapty` ve `AdaptyUI` pod'larını kaldırın, `pod install` çalıştırarak temizleyin, ardından Xcode'da **File → Add Package Dependency** seçeneğiyle `https://github.com/adaptyteam/AdaptySDK-iOS.git` adresini kullanarak paketi ekleyin.
## Kids Mode: ayrı ürünler bir paket özelliğiyle değiştirildi \{#kids-mode-separate-products-replaced-by-a-package-trait\}
v3'te, [Kids Mode](kids-mode)'u etkinleştirmek için ayrı **Adapty_KidsMode** ve **AdaptyUI_KidsMode** paket ürünlerini seçiyor ve importlarınızı yeniden adlandırıyordunuz. v4.0'da bu ürünler kaldırıldı. Kids Mode artık normal Adapty paketinde `KidsMode` adlı bir Swift paket özelliği — etkinleştirildiğinde IDFA ve AdSupport'u tüm SDK genelinde derlemenin dışında bırakır.
Geçiş yapmak için:
1. **Choose Package Products** penceresinde, **Adapty_KidsMode** ve **AdaptyUI_KidsMode** yerine normal **Adapty** ve **AdaptyUI** ürünlerini seçin.
2. `KidsMode` trait'ini etkinleştirin. Xcode 26.4 veya sonraki bir sürümde, projenizin **Package Dependencies** görünümünde AdaptySDK-iOS bağımlılığı için etkinleştirin. Adapty'yi `Package.swift` içine bağımlılık olarak ekliyorsanız (`swift-tools-version` 6.1 veya sonrası gereklidir), orada etkinleştirin:
```swift showLineNumbers title="Package.swift"
.package(
url: "https://github.com/adaptyteam/AdaptySDK-iOS.git",
from: "4.0.0",
traits: ["KidsMode"]
)
```
3. Import'larınızı tekrar normal modüllere geri alın:
```diff showLineNumbers
- import Adapty_KidsMode
- import AdaptyUI_KidsMode
+ import Adapty
+ import AdaptyUI
```
:::note
26.4'ten eski Xcode sürümleri, bir Xcode projesinde trait'leri arayüzden etkinleştiremez. Bu durumda, `KidsMode` trait'i etkin şekilde Adapty'ye bağımlı küçük bir yerel Swift paketi oluşturun ve uygulama hedefinizi bu pakete bağımlı yapın.
:::
## Kaldırılan API'ler \{#removed-apis\}
- **`Adapty.getPaywallProductsWithoutDeterminingOffer(paywall:)`** — kaldırıldı. Artık tüm ürünler teklif bilgisini içerdiğinden, ayrı bir uygunluk kontrolü adımına gerek kalmadı.
- **`AdaptyPaywallProductWithoutDeterminingOffer`** — kaldırıldı. Daha önce bu türü (örneğin `didSelectProduct` gibi) callback'lere geçiren yapılar artık `AdaptyPaywallProduct` kullanıyor.
## App Store tanıtılan uygulama içi satın almalar geçici olarak kaldırıldı \{#app-store-promoted-in-app-purchases-temporarily-removed\}
StoreKit 2 geçişinin bir parçası olarak, Adapty iOS SDK 4.0, App Store tanıtılan uygulama içi satın almalar için desteği kaldırdı. `shouldAddStorePayment(for:)` delegate metodu ve aldığı `AdaptyDeferredProduct` türü 4.0'da kullanılamamaktadır.
:::warning
Bu kaldırma işlemi geçicidir — tanıtılan uygulama içi satın alma desteği daha sonraki bir 4.x sürümünde geri dönecektir. Uygulamanız tanıtılan uygulama içi satın almalara dayanıyorsa, destek geri dönene kadar iOS SDK 3.x sürümünde kalmaya devam edin.
:::
## Paywall'ları Getirme \{#fetching-paywalls\}
### getPaywall + getPaywallConfiguration → getFlow + getFlowConfiguration
Döndürülen türler `AdaptyPaywall` / `AdaptyUI.PaywallConfiguration` yerine `AdaptyFlow` / `AdaptyUI.FlowConfiguration` olarak değişiyor. `locale` parametresi fetch çağrısından çıkarılıp `getFlowConfiguration` üzerine taşınıyor:
```diff showLineNumbers
- let paywall = try await Adapty.getPaywall(placementId: "YOUR_PLACEMENT_ID", locale: "en")
- let paywallConfiguration = try await AdaptyUI.getPaywallConfiguration(forPaywall: paywall)
+ let flow = try await Adapty.getFlow(placementId: "YOUR_PLACEMENT_ID")
+ let flowConfiguration = try await AdaptyUI.getFlowConfiguration(forFlow: flow, locale: "en")
```
### getPaywallProducts(paywall:) → getPaywallProducts(flow:)
`getPaywallProducts` artık `Adapty.getFlow` tarafından döndürülen bir `AdaptyFlow` alıyor:
```diff showLineNumbers
- let products = try await Adapty.getPaywallProducts(paywall: paywall)
+ let products = try await Adapty.getPaywallProducts(flow: flow)
```
## Paywall görüntülemelerini takip etme \{#tracking-paywall-views\}
### logShowPaywall(_:) → logShowFlow(_:)
`logShowPaywall`, `logShowFlow` olarak yeniden adlandırıldı ve artık `AdaptyPaywall` yerine `AdaptyFlow` alıyor. Olay hâlâ aynı varyasyona karşı kaydedildiği için mevcut dönüşüm hunisi ve A/B testi metrikleri kontrol panelinde herhangi bir değişiklik yapılmadan çalışmaya devam eder.
```diff showLineNumbers
- try await Adapty.logShowPaywall(paywall)
+ try await Adapty.logShowFlow(flow)
```
v3'te olduğu gibi, [Flow Builder](adapty-flow-builder) veya [Paywall Builder](adapty-paywall-builder) tarafından oluşturulan flow veya paywall'ları görüntülerken bu metodu çağırmanız gerekmez — Adapty bu görüntülemeleri otomatik olarak takip eder.
## didFinishPurchase artık zorunlu \{#didfinishpurchase-is-now-required\}
v3'te `didFinishPurchase` isteğe bağlıydı: uygulamamanız durumunda, başarılı bir satın alma işleminin ardından paywall kendiliğinden kapanıyordu. v4.0'da bu varsayılan otomatik kapanma davranışı kaldırıldı; böylece başarılı bir satın alma işleminin ardından flow devam edebilir — örneğin flow'unuzun geri kalan ekranlarını göstermek için. Satın alma işleminin ardından ne olacağına artık siz karar veriyorsunuz: ekranı kapatın ya da flow'un devam etmesine izin vermek için hiçbir şey yapmayın.
- **UIKit**: `AdaptyFlowControllerDelegate` uyumluları artık `didFinishPurchase` metodunu uygulamak zorundadır — bu metodun artık varsayılan bir implementasyonu yoktur.
- **SwiftUI**: `.flow(...)` ve `AdaptyFlowView(...)` içindeki `didFinishPurchase` closure'ı artık zorunludur (non-optional); bu durum `didFailPurchase` ve `didFinishRestore` ile tutarlı hale getirilmiştir.
v3 davranışını korumak için ekranı kendiniz kapatın:
```swift showLineNumbers title="Swift"
func flowController(
_ controller: AdaptyFlowController,
didFinishPurchase product: AdaptyPaywallProduct,
purchaseResult: AdaptyPurchaseResult
) {
if !purchaseResult.isPurchaseCancelled {
controller.dismiss(animated: true)
}
}
```
## UIKit \{#uikit\}
### AdaptyPaywallController → AdaptyFlowController
Kontrolcü türünü ve fabrika metodunu yeniden adlandırın:
```diff showLineNumbers
- let controller = try AdaptyUI.paywallController(
- with: paywallConfiguration,
- delegate: self
- )
+ let controller = try AdaptyUI.flowController(
+ with: flowConfiguration,
+ delegate: self
+ )
```
### AdaptyPaywallControllerDelegate → AdaptyFlowControllerDelegate
Protokolü yeniden adlandırın ve her metot imzasını güncelleyin. `didSelectProduct` artık kaldırılan `AdaptyPaywallProductWithoutDeterminingOffer` yerine `AdaptyPaywallProduct` alıyor; `didFinishPurchase` ise [artık zorunlu olarak uygulanmalıdır](#didfinishpurchase-is-now-required) — varsayılan bir implementasyonu kalmadı.
```diff showLineNumbers
- class YourClass: AdaptyPaywallControllerDelegate {
+ class YourClass: AdaptyFlowControllerDelegate {
- func paywallControllerDidAppear(_ controller: AdaptyPaywallController) { }
+ func flowControllerDidAppear(_ controller: AdaptyFlowController) { }
- func paywallControllerDidDisappear(_ controller: AdaptyPaywallController) { }
+ func flowControllerDidDisappear(_ controller: AdaptyFlowController) { }
- func paywallController(_ controller: AdaptyPaywallController,
- didPerform action: AdaptyUI.Action) { }
+ func flowController(_ controller: AdaptyFlowController,
+ didPerform action: AdaptyUI.Action) { }
- func paywallController(_ controller: AdaptyPaywallController,
- didSelectProduct product: AdaptyPaywallProductWithoutDeterminingOffer) { }
+ func flowController(_ controller: AdaptyFlowController,
+ didSelectProduct product: AdaptyPaywallProduct) { }
- func paywallController(_ controller: AdaptyPaywallController,
- didStartPurchase product: AdaptyPaywallProduct) { }
+ func flowController(_ controller: AdaptyFlowController,
+ didStartPurchase product: AdaptyPaywallProduct) { }
- func paywallController(_ controller: AdaptyPaywallController,
- didFinishPurchase product: AdaptyPaywallProduct,
- purchaseResult: AdaptyPurchaseResult) { }
+ func flowController(_ controller: AdaptyFlowController,
+ didFinishPurchase product: AdaptyPaywallProduct,
+ purchaseResult: AdaptyPurchaseResult) { }
- func paywallController(_ controller: AdaptyPaywallController,
- didFailPurchase product: AdaptyPaywallProduct,
- error: AdaptyError) { }
+ func flowController(_ controller: AdaptyFlowController,
+ didFailPurchase product: AdaptyPaywallProduct,
+ error: AdaptyError) { }
- func paywallControllerDidStartRestore(_ controller: AdaptyPaywallController) { }
+ func flowControllerDidStartRestore(_ controller: AdaptyFlowController) { }
- func paywallController(_ controller: AdaptyPaywallController,
- didFinishRestoreWith profile: AdaptyProfile) { }
+ func flowController(_ controller: AdaptyFlowController,
+ didFinishRestoreWith profile: AdaptyProfile) { }
- func paywallController(_ controller: AdaptyPaywallController,
- didFailRestoreWith error: AdaptyError) { }
+ func flowController(_ controller: AdaptyFlowController,
+ didFailRestoreWith error: AdaptyError) { }
- func paywallController(_ controller: AdaptyPaywallController,
- didFailRenderingWith error: AdaptyUIError) { }
+ func flowController(_ controller: AdaptyFlowController,
+ didReceiveError error: AdaptyUIError) { }
- func paywallController(_ controller: AdaptyPaywallController,
- didFailLoadingProductsWith error: AdaptyError) -> Bool { }
+ func flowController(_ controller: AdaptyFlowController,
+ didFailLoadingProductsWith error: AdaptyError) -> Bool { }
- func paywallController(_ controller: AdaptyPaywallController,
- didPartiallyLoadProducts failedIds: [String]) { }
+ func flowController(_ controller: AdaptyFlowController,
+ didPartiallyLoadProducts failedIds: [String]) { }
- func paywallController(_ controller: AdaptyPaywallController,
- didFinishWebPaymentNavigation product: AdaptyPaywallProduct?,
- error: AdaptyError?) { }
+ func flowController(_ controller: AdaptyFlowController,
+ didFinishWebPaymentNavigation product: AdaptyPaywallProduct?,
+ error: AdaptyError?) { }
}
```
## SwiftUI \{#swiftui\}
### .paywall() modifier → .flow() \{#paywall-modifier--flow\}
Modifier adını değiştirin, yapılandırma parametre adını güncelleyin ve [artık zorunlu olan](#didfinishpurchase-is-now-required) `didFinishPurchase` closure'ını ekleyin:
```diff showLineNumbers
@State var flowPresented = false // rename freely — the variable name is your choice
var body: some View {
Text("Hello, AdaptyUI!")
- .paywall(
+ .flow(
isPresented: $flowPresented,
- paywallConfiguration: paywallConfiguration,
+ flowConfiguration: flowConfiguration,
+ didFinishPurchase: { product, purchaseResult in /* dismiss, or do nothing to let the flow continue */ },
didFailPurchase: { product, error in /* handle the error */ },
didFinishRestore: { profile in /* check access level and dismiss */ },
didFailRestore: { error in /* handle the error */ },
- didFailRendering: { error in flowPresented = false }
+ didReceiveError: { error in flowPresented = false }
)
}
```
Yeniden adlandırılan callback, `didFailRendering`'in tetiklendiği tüm render hatalarında olduğu gibi, flow script'inden gelen yeni çalışma zamanı hatalarında da (`AdaptyUIError` kodu `4105` — `.jsException` olan JavaScript istisnaları) tetiklenir. Mevcut handler gövdelerinde kod değişikliği gerekmez — yalnızca parametreyi yeniden adlandırın.
### AdaptyPaywallView → AdaptyFlowView
Görünümü yeniden adlandırın, yapılandırma parametresini güncelleyin, [artık zorunlu olan](#didfinishpurchase-is-now-required) `didFinishPurchase` closure'ını ekleyin ve varsa `didSelectProduct` closure'ını güncelleyin — artık kaldırılan `AdaptyPaywallProductWithoutDeterminingOffer` yerine `AdaptyPaywallProduct` alıyor:
```diff showLineNumbers
- AdaptyPaywallView(
- paywallConfiguration: paywallConfiguration,
- didSelectProduct: { product: AdaptyPaywallProductWithoutDeterminingOffer in /* handle */ },
+ AdaptyFlowView(
+ flowConfiguration: flowConfiguration,
+ didSelectProduct: { product: AdaptyPaywallProduct in /* handle */ },
+ didFinishPurchase: { product, purchaseResult in /* dismiss, or do nothing to let the flow continue */ },
didFailPurchase: { product, error in /* handle the error */ },
didFinishRestore: { profile in /* check access level and dismiss */ },
didFailRestore: { error in /* handle the error */ },
- didFailRendering: { error in /* handle the error */ }
+ didReceiveError: { error in /* handle the error */ }
)
```
## AdaptyUI özel varlıklar \{#adaptyui-custom-assets\}
### AdaptyUICustomVideoAsset
Mevcut her çağrı noktasını etkileyen iki değişiklik:
- `.player` artık `AVQueuePlayer` yerine `AVPlayer` alıyor.
- Her case'e sonda `resolution: CGSize?` parametresi eklendi. Mevcut davranışı korumak için `nil` geçin ya da video yüklenmeden önce yerleşim alanını ayırt etmesi (en-boy oranı = `width / height`) için gerçek piksel boyutunu belirtin.
```diff showLineNumbers
- case file(url: URL, preview: AdaptyUICustomImageAsset?)
- case remote(url: URL, preview: AdaptyUICustomImageAsset?)
- case player(item: AVPlayerItem, player: AVQueuePlayer, preview: AdaptyUICustomImageAsset?)
+ case file(url: URL, preview: AdaptyUICustomImageAsset?, resolution: CGSize?)
+ case remote(url: URL, preview: AdaptyUICustomImageAsset?, resolution: CGSize?)
+ case player(item: AVPlayerItem, player: AVPlayer, preview: AdaptyUICustomImageAsset?, resolution: CGSize?)
```
## Attribution ve entegrasyon tanımlayıcıları \{#attribution-and-integration-identifiers\}
### updateAttribution(_:source:)
`source` parametresi `String` yerine yeni `AdaptyAttributionSource` türünü kullanıyor; daha önce iç içe olan `AdaptyProfile.AttributionSource` ise üst düzey `AdaptyAttributionSource` olarak yeniden adlandırıldı. Önceden tanımlanmış kaynaklardan birini kullanabilir ya da başka bir kaynak için string literal geçirebilirsiniz — `AdaptyAttributionSource`, `ExpressibleByStringLiteral` protokolüne uyduğundan mevcut string literal çağrıları derlemeye devam eder.
```diff showLineNumbers
- try await Adapty.updateAttribution(attribution, source: "adjust")
+ try await Adapty.updateAttribution(attribution, source: .adjust)
```
Önceden tanımlanmış kaynaklar: `.appleAds`, `.adjust`, `.appsflyer`, `.branch`, `.tenjin`. Kaynağı bir `String` değişkeninde tutuyorsanız şu şekilde sarmalayın: `AdaptyAttributionSource(rawValue: yourSource)`.
### setIntegrationIdentifier(_:)
`setIntegrationIdentifier(key:value:)`, bir veya daha fazla `AdaptyIntegrationIdentifier` değeri alan değişken sayıda parametre kabul eden bir metotla değiştirildi. Ham string anahtarlar yerine önceden tanımlanmış fabrika metotlarını kullanın:
```diff showLineNumbers
- try await Adapty.setIntegrationIdentifier(key: "appsflyer_id", value: uid)
+ try await Adapty.setIntegrationIdentifier(.appsflyerId(uid))
```
Tek bir çağrıda birden fazla tanımlayıcı ayarlayabilirsiniz:
```swift showLineNumbers
try await Adapty.setIntegrationIdentifier(
.appsflyerId(uid),
.adjustDeviceId(adid)
)
```
Her eski anahtar dizesini fabrika metoduyla değiştirin:
| v3 anahtarı | v4 factory |
|---|---|
| `"adjust_device_id"` | `.adjustDeviceId(_:)` |
| `"airbridge_device_id"` | `.airbridgeDeviceId(_:)` |
| `"amplitude_user_id"` | `.amplitudeUserId(_:)` |
| `"amplitude_device_id"` | `.amplitudeDeviceId(_:)` |
| `"appmetrica_device_id"` | `.appmetricaDeviceId(_:)` |
| `"appmetrica_profile_id"` | `.appmetricaProfileId(_:)` |
| `"appsflyer_id"` | `.appsflyerId(_:)` |
| `"branch_id"` | `.branchId(_:)` |
| `"facebook_anonymous_id"` | `.facebookAnonymousId(_:)` |
| `"firebase_app_instance_id"` | `.firebaseAppInstanceId(_:)` |
| `"mixpanel_user_id"` | `.mixpanelUserId(_:)` |
| `"one_signal_subscription_id"` | `.oneSignalSubscriptionId(_:)` |
| `"one_signal_player_id"` | `.oneSignalPlayerId(_:)` |
| `"posthog_distinct_user_id"` | `.posthogDistinctUserId(_:)` |
| `"pushwoosh_hwid"` | `.pushwooshHWID(_:)` |
| `"tenjin_analytics_installation_id"` | `.tenjinAnalyticsInstallationId(_:)` |
---
# File: migration-to-ios-315
---
---
title: "Adapty iOS SDK'yı v3.15'e Geçirin"
description: "Daha iyi performans ve yeni monetizasyon özellikleri için Adapty iOS SDK v3.15'e geçin."
---
[Paywall Builder](adapty-paywall-builder)'ı [Observer mode](observer-vs-full-mode)'da kullanıyorsanız, iOS SDK 3.15'ten itibaren yeni bir `observerModeDidInitiateRestorePurchases(onStartRestore:onFinishRestore:)` metodu uygulamanız gerekiyor. Bu metot, satın alma işlemlerini geri yükleme mantığı üzerinde daha fazla kontrol sağlayarak bunları kendi özel flow'unuzda yönetmenize olanak tanır. Tam uygulama ayrıntıları için [Observer mode'da Paywall Builder paywall'larını sunma](ios-present-paywall-builder-paywalls-in-observer-mode) sayfasına bakın.
```diff showLineNumbers
func observerMode(didInitiatePurchase product: AdaptyPaywallProduct,
onStartPurchase: @escaping () -> Void,
onFinishPurchase: @escaping () -> Void) {
// use the product object to handle the purchase
// use the onStartPurchase and onFinishPurchase callbacks to notify AdaptyUI about the process of the purchase
}
+ func observerModeDidInitiateRestorePurchases(onStartRestore: @escaping () -> Void,
+ onFinishRestore: @escaping () -> Void) {
+ // use the onStartRestore and onFinishRestore callbacks to notify AdaptyUI about the process of the restore
+ }
```
---
# File: migration-to-ios-sdk-34
---
---
title: "Adapty iOS SDK'yı v3.4'e Taşıma"
description: "Daha iyi performans ve yeni para kazanma özellikleri için Adapty iOS SDK v3.4'e geçiş yapın."
---
Adapty SDK 3.4.0, büyük bir sürümdür ve sizin tarafınızda geçiş adımları gerektiren iyileştirmeler içermektedir.
## Adapty SDK aktivasyonunu güncelleme \{#update-adapty-sdk-activation\}
```diff showLineNumbers
// In your AppDelegate class:
let configurationBuilder =
AdaptyConfiguration
.builder(withAPIKey: "PUBLIC_SDK_KEY")
- Adapty.activate(with: configurationBuilder) { error in
+ Adapty.activate(with: configurationBuilder.build()) { error in
// handle the error
}
```
**Yedek paywall dosyalarını güncelleme**
Yeni SDK sürümüyle uyumluluğu sağlamak için yedek paywall dosyalarınızı güncelleyin:
1. Adapty Kontrol Paneli'nden [güncellenmiş yedek paywall dosyalarını indirin](fallback-paywalls).
2. Mobil uygulamanızdaki mevcut yedek paywallları [yeni dosyalarla değiştirin](ios-use-fallback-paywalls).
```diff showLineNumbers
@main
struct SampleApp: App {
init() {
let configurationBuilder =
AdaptyConfiguration
.builder(withAPIKey: "PUBLIC_SDK_KEY")
Task {
- try await Adapty.activate(with: configurationBuilder)
+ try await Adapty.activate(with: configurationBuilder.build())
}
}
var body: some Scene {
WindowGroup {
ContentView()
}
}
}
```
**Yedek paywall dosyalarını güncelleme**
Yeni SDK sürümüyle uyumluluğu sağlamak için yedek paywall dosyalarınızı güncelleyin:
1. Adapty Kontrol Paneli'nden [güncellenmiş yedek paywall dosyalarını indirin](fallback-paywalls).
2. Mobil uygulamanızdaki mevcut yedek paywallları [yeni dosyalarla değiştirin](ios-use-fallback-paywalls).
---
# File: migration-to-ios330
---
---
title: "Adapty iOS SDK'yı v3.3'e Taşıyın"
description: "Daha iyi performans ve yeni para kazanma özellikleri için Adapty iOS SDK v3.3'e geçiş yapın."
---
Adapty SDK 3.3.0, bazı iyileştirmeler getiren önemli bir sürümdür; ancak bu iyileştirmeler sizin tarafınızdan bazı geçiş adımları gerektirebilir.
1. `Adapty.Configuration`'ı `AdaptyConfiguration` olarak yeniden adlandırın.
2. `getViewConfiguration` metodunu `getPaywallConfiguration` olarak yeniden adlandırın.
3. SwiftUI'dan `didCancelPurchase` ve `paywall` parametrelerini kaldırın ve `viewConfiguration` parametresini `paywallConfiguration` olarak yeniden adlandırın.
4. App Store'dan gelen promosyon içi uygulama satın almalarını işleme şeklinizi güncelleyin; `AdaptyDelegate` metodundan `defermentCompletion` parametresini kaldırın.
5. `getProductsIntroductoryOfferEligibility` metodunu kaldırın.
6. Adjust, AirBridge, Amplitude, AppMetrica, Appsflyer, Branch, Facebook Ads, Firebase ve Google Analytics, Mixpanel, OneSignal, Pushwoosh için entegrasyon yapılandırmalarını güncelleyin.
7. Observer modu uygulamasını güncelleyin.
## Adapty.Configuration'ı AdaptyConfiguration Olarak Yeniden Adlandırın \{#rename-adaptyconfiguration-to-adaptyconfiguration\}
Adapty iOS SDK aktivasyon kodunu aşağıdaki şekilde güncelleyin:
```diff showLineNumbers
// In your AppDelegate class:
let configurationBuilder =
- Adapty.Configuration
+ AdaptyConfiguration
.builder(withAPIKey: "PUBLIC_SDK_KEY")
.with(observerMode: false)
.with(customerUserId: "YOUR_USER_ID")
.with(idfaCollectionDisabled: false)
.with(ipAddressCollectionDisabled: false)
Adapty.activate(with: configurationBuilder) { error in
// handle the error
}
```
```diff showLineNumbers
@main
struct SampleApp: App {
init()
let configurationBuilder =
- Adapty.Configuration
+ AdaptyConfiguration
.builder(withAPIKey: "PUBLIC_SDK_KEY")
.with(observerMode: false) // optional
.with(customerUserId: "YOUR_USER_ID") // optional
.with(idfaCollectionDisabled: false) // optional
.with(ipAddressCollectionDisabled: false) // optional
Task {
try await Adapty.activate(with: configurationBuilder)
}
}
var body: some Scene {
WindowGroup {
ContentView()
}
}
}
```
## getViewConfiguration metodunu getPaywallConfiguration olarak yeniden adlandırın \{#rename-getviewconfiguration-method-to-getpaywallconfiguration\}
Paywall'ın `viewConfiguration` değerini getiren metodun adını güncelleyin:
```diff showLineNumbers
guard paywall.hasViewConfiguration else {
// use your custom logic
return
}
do {
- let paywallConfiguration = try await AdaptyUI.getViewConfiguration(
+ let paywallConfiguration = try await AdaptyUI.getPaywallConfiguration(
forPaywall: paywall
)
// use loaded configuration
} catch {
// handle the error
}
```
Paywall Builder kullanılarak tasarlanan paywallın görünüm yapılandırmasını getirme hakkında daha fazla bilgi için [Paywall Builder ile tasarlanan paywallın görünüm yapılandırmasını getirme](get-pb-paywalls#fetch-the-view-configuration-of-paywall-designed-using-paywall-builder) bölümüne bakın.
## SwiftUI'daki parametreleri güncelleme \{#change-parameters-in-swiftui\}
SwiftUI'da aşağıdaki güncellemeler yapılmıştır:
1. `didCancelPurchase` parametresi kaldırıldı. Bunun yerine `didFinishPurchase` kullanın.
2. `.paywall()` metodu artık bir paywall nesnesi kabul etmiyor.
3. `paywallConfiguration` parametresi, `viewConfiguration` parametresinin yerini aldı.
Kodunuzu aşağıdaki şekilde güncelleyin:
```diff showLineNumbers
@State var paywallPresented = false
var body: some View {
Text("Hello, AdaptyUI!")
.paywall(
isPresented: $paywallPresented,
- paywall: ,
- viewConfiguration: ,
+ paywallConfiguration: ,
didPerformAction: { action in
switch action {
case .close:
paywallPresented = false
default:
// Handle other actions
break
}
},
- didFinishPurchase: { product, profile in paywallPresented = false },
+ didFinishPurchase: { product, purchaseResult in /* handle the result*/ },
didFailPurchase: { product, error in /* handle the error */ },
didFinishRestore: { profile in /* check access level and dismiss */ },
didFailRestore: { error in /* handle the error */ },
didFailRendering: { error in paywallPresented = false }
- didCancelPurchase: { product in /* handle the result*/}
)
}
```
## App Store'dan gelen promosyonlu uygulama içi satın almaların işlenmesini güncelleme \{#update-handling-of-promotional-in-app-purchases-from-app-store\}
Aşağıdaki örnekte gösterildiği gibi, `AdaptyDelegate` metodundan `defermentCompletion` parametresini kaldırarak App Store'dan gelen promosyonlu uygulama içi satın almaların işlenme biçimini güncelleyin:
```swift showLineNumbers title="Swift"
final class YourAdaptyDelegateImplementation: AdaptyDelegate {
nonisolated func shouldAddStorePayment(for product: AdaptyDeferredProduct) -> Bool {
// 1a.
// Return `true` to continue the transaction in your app.
// 1b.
// Store the product object and return `false` to defer or cancel the transaction.
false
}
// 2. Continue the deferred purchase later on by passing the product to `makePurchase`
func continueDeferredPurchase() async {
let storedProduct: AdaptyDeferredProduct = // get the product object from the 1b.
do {
try await Adapty.makePurchase(product: storedProduct)
} catch {
// handle the error
}
}
}
```
## getProductsIntroductoryOfferEligibility metodunu kaldırın \{#remove-getproductsintroductoryoffereligibility-method\}
Adapty iOS SDK 3.3.0 öncesinde, ürün nesnesi kullanıcının uygunluğundan bağımsız olarak her zaman teklifleri içeriyordu. Teklifi kullanmadan önce uygunluğu elle kontrol etmeniz gerekiyordu.
Artık ürün nesnesi yalnızca kullanıcı uygunsa teklif içeriyor. Bu, uygunluğu artık kontrol etmeniz gerekmediği anlamına geliyor — bir teklif mevcutsa kullanıcı zaten uygun demektir.
Uygun olmayan kullanıcılar için teklifleri görüntülemek istiyorsanız `sk1Product` ve `sk2Product`'a başvurun.
## Üçüncü taraf entegrasyon SDK yapılandırmasını güncelleyin \{#update-third-party-integration-sdk-configuration\}
Adapty iOS SDK 3.3.0 ile birlikte `updateAttribution` metodunun genel API'sini güncelledik. Önceden `[AnyHashable: Any]` sözlüğü kabul ederek çeşitli servislerden attribution nesnelerini doğrudan iletmenize olanak tanıyordu. Artık `[String: any Sendable]` gerektiriyor; bu nedenle attribution nesnelerini iletmeden önce dönüştürmeniz gerekiyor.
Adapty iOS SDK 3.3.0 ve sonrasında entegrasyonların düzgün çalışmasını sağlamak için aşağıdaki entegrasyonların SDK yapılandırmalarını aşağıdaki bölümlerde açıklandığı gibi güncelleyin.
### Adjust
Mobil uygulama kodunuzu aşağıda gösterildiği gibi güncelleyin. Tam kod örneği için [Adjust entegrasyonu için SDK yapılandırması](adjust#connect-your-app-to-adjust) sayfasına bakın.
```diff showLineNumbers
class AdjustModuleImplementation {
- func updateAdjustAttribution() {
- Adjust.attribution { attribution in
- guard let attributionDictionary = attribution?.dictionary()?.toSendableDict() else { return }
-
- Adjust.adid { adid in
- guard let adid else { return }
-
- Adapty.updateAttribution(attributionDictionary, source: .adjust, networkUserId: adid) { error in
- // handle the error
- }
- }
- }
- }
+ func updateAdjustAdid() {
+ Adjust.adid { adid in
+ guard let adid else { return }
+
+ Adapty.setIntegrationIdentifier(key: "adjust_device_id", value: adid)
+ }
+ }
+
+ func updateAdjustAttribution() {
+ Adjust.attribution { attribution in
+ guard let attribution = attribution?.dictionary() else {
+ return
+ }
+
+ Adapty.updateAttribution(attribution, source: "adjust")
+ }
+ }
}
```
```diff showLineNumbers
class YourAdjustDelegateImplementation {
// Find your implementation of AdjustDelegate
// and update adjustAttributionChanged method:
func adjustAttributionChanged(_ attribution: ADJAttribution?) {
- if let attribution = attribution?.dictionary()?.toSendableDict() {
- Adapty.updateAttribution(attribution, source: .adjust)
+ if let attribution = attribution?.dictionary() {
+ Adapty.updateAttribution(attribution, source: "adjust")
}
}
}
```
### AirBridge
Mobil uygulama kodunuzu aşağıda gösterildiği gibi güncelleyin. Tam kod örneği için bkz. [AirBridge entegrasyonu için SDK yapılandırması](airbridge#connect-your-app-to-airbridge).
```diff showLineNumbers
import AirBridge
- let builder = AdaptyProfileParameters.Builder()
- .with(airbridgeDeviceId: AirBridge.deviceUUID())
-
- Adapty.updateProfile(params: builder.build())
+ do {
+ try await Adapty.setIntegrationIdentifier(
+ key: "airbridge_device_id",
+ value: AirBridge.deviceUUID()
+ )
+ } catch {
+ // handle the error
+ }
```
### Amplitude
Mobil uygulama kodunuzu aşağıda gösterildiği gibi güncelleyin. Tam kod örneği için [Amplitude entegrasyonu için SDK yapılandırması](amplitude#sdk-configuration) bölümüne bakın.
```diff showLineNumbers
import Amplitude
- let builder = AdaptyProfileParameters.Builder()
- .with(amplitudeUserId: Amplitude.instance().userId)
- .with(amplitudeDeviceId: Amplitude.instance().deviceId)
-
- Adapty.updateProfile(params: builder.build())
+ do {
+ try await Adapty.setIntegrationIdentifier(
+ key: "amplitude_user_id",
+ value: Amplitude.instance().userId
+ )
+ try await Adapty.setIntegrationIdentifier(
+ key: "amplitude_device_id",
+ value: Amplitude.instance().deviceId
+ )
+ } catch {
+ // handle the error
+ }
```
### AppMetrica
Mobil uygulama kodunuzu aşağıdaki gibi güncelleyin. Tam kod örneği için [AppMetrica entegrasyonunda SDK yapılandırması](appmetrica#sdk-configuration) bölümüne bakın.
```diff showLineNumbers
import AppMetricaCore
- if let deviceID = AppMetrica.deviceID {
- let builder = AdaptyProfileParameters.Builder()
- .with(appmetricaDeviceId: deviceID)
- .with(appmetricaProfileId: "YOUR_ADAPTY_CUSTOMER_USER_ID")
-
- Adapty.updateProfile(params: builder.build())
- }
+ if let deviceID = AppMetrica.deviceID {
+ do {
+ try await Adapty.setIntegrationIdentifier(
+ key: "appmetrica_device_id",
+ value: deviceID
+ )
+ try await Adapty.setIntegrationIdentifier(
+ key: "appmetrica_profile_id",
+ value: "YOUR_ADAPTY_CUSTOMER_USER_ID"
+ )
+ } catch {
+ // handle the error
+ }
+ }
```
### AppsFlyer
Mobil uygulama kodunuzu aşağıda gösterildiği gibi güncelleyin. Tam kod örneği için [AppsFlyer entegrasyonu için SDK yapılandırması](appsflyer#connect-your-app-to-appsflyer) sayfasına bakın.
```diff showLineNumbers
class YourAppsFlyerLibDelegateImplementation {
// Find your implementation of AppsFlyerLibDelegate
// and update onConversionDataSuccess method:
func onConversionDataSuccess(_ conversionInfo: [AnyHashable : Any]) {
let uid = AppsFlyerLib.shared().getAppsFlyerUID()
- Adapty.updateAttribution(
- conversionInfo.toSendableDict(),
- source: .appsflyer,
- networkUserId: uid
- )
+ Adapty.setIntegrationIdentifier(key: "appsflyer_id", value: uid)
+ Adapty.updateAttribution(conversionInfo, source: "appsflyer")
}
}
```
### Branch
Mobil uygulama kodunuzu aşağıda gösterildiği gibi güncelleyin. Tam kod örneği için [Branch entegrasyonu için SDK yapılandırmasına](branch#connect-your-app-to-branch) bakın.
```diff showLineNumbers
class YourBranchImplementation {
func initializeBranch() {
// Pass the attribution you receive from the initializing method of Branch iOS SDK to Adapty.
Branch.getInstance().initSession(launchOptions: launchOptions) { (data, error) in
- if let data = data?.toSendableDict() {
- Adapty.updateAttribution(data, source: .branch)
- }
+ if let data {
+ Adapty.updateAttribution(data, source: "branch")
+ }
}
}
}
```
### Facebook Ads
Mobil uygulama kodunuzu aşağıda gösterildiği şekilde güncelleyin. Tam kod örneği için [Facebook Ads entegrasyonu için SDK yapılandırması](facebook-ads#connect-your-app-to-facebook-ads) bölümüne bakın.
```diff showLineNumbers
import FacebookCore
- let builder = AdaptyProfileParameters.Builder()
- .with(facebookAnonymousId: AppEvents.shared.anonymousID)
-
- do {
- try Adapty.updateProfile(params: builder.build())
- } catch {
- // handle the error
- }
+ do {
+ try await Adapty.setIntegrationIdentifier(
+ key: "facebook_anonymous_id",
+ value: AppEvents.shared.anonymousID
+ )
+ } catch {
+ // handle the error
+ }
```
### Firebase ve Google Analytics \{#firebase-and-google-analytics\}
Mobil uygulama kodunuzu aşağıda gösterildiği gibi güncelleyin. Tam kod örneği için [Firebase ve Google Analytics entegrasyonu için SDK yapılandırması](firebase-and-google-analytics) sayfasına bakın.
```diff showLineNumbers
import FirebaseCore
import FirebaseAnalytics
FirebaseApp.configure()
- if let appInstanceId = Analytics.appInstanceID() {
- let builder = AdaptyProfileParameters.Builder()
- .with(firebaseAppInstanceId: appInstanceId)
- Adapty.updateProfile(params: builder.build()) { error in
- // handle error
- }
- }
+ if let appInstanceId = Analytics.appInstanceID() {
+ do {
+ try await Adapty.setIntegrationIdentifier(
+ key: "firebase_app_instance_id",
+ value: appInstanceId
+ )
+ } catch {
+ // handle the error
+ }
+ }
```
### Mixpanel
Mobil uygulama kodunuzu aşağıda gösterildiği gibi güncelleyin. Tam kod örneği için [Mixpanel entegrasyonunda SDK yapılandırması](mixpanel#sdk-configuration) bölümüne bakın.
```diff showLineNumbers
import Mixpanel
- let builder = AdaptyProfileParameters.Builder()
- .with(mixpanelUserId: Mixpanel.mainInstance().distinctId)
-
- do {
- try await Adapty.updateProfile(params: builder.build())
- } catch {
- // handle the error
- }
+ do {
+ try await Adapty.setIntegrationIdentifier(
+ key: "mixpanel_user_id",
+ value: Mixpanel.mainInstance().distinctId
+ )
+ } catch {
+ // handle the error
+ }
```
### OneSignal
Aşağıda gösterildiği şekilde mobil uygulama kodunuzu güncelleyin. Tam kod örneği için [OneSignal entegrasyonu için SDK yapılandırması](onesignal#sdk-configuration) sayfasına bakın.
```diff showLineNumbers
// PlayerID (pre-v5 OneSignal SDK)
// in your OSSubscriptionObserver implementation
func onOSSubscriptionChanged(_ stateChanges: OSSubscriptionStateChanges) {
if let playerId = stateChanges.to.userId {
- let params = AdaptyProfileParameters.Builder()
- .with(oneSignalPlayerId: playerId)
- .build()
-
- Adapty.updateProfile(params:params) { error in
- // check error
- }
+ Task {
+ try await Adapty.setIntegrationIdentifier(
+ key: "one_signal_player_id",
+ value: playerId
+ )
+ }
}
}
// SubscriptionID (v5+ OneSignal SDK)
OneSignal.Notifications.requestPermission({ accepted in
- let id = OneSignal.User.pushSubscription.id
-
- let builder = AdaptyProfileParameters.Builder()
- .with(oneSignalSubscriptionId: id)
-
- Adapty.updateProfile(params: builder.build())
+ Task {
+ try await Adapty.setIntegrationIdentifier(
+ key: "one_signal_subscription_id",
+ value: OneSignal.User.pushSubscription.id
+ )
+ }
}, fallbackToSettings: true)
```
### Pushwoosh
Mobil uygulama kodunuzu aşağıda gösterildiği gibi güncelleyin. Tam kod örneği için [Pushwoosh entegrasyonunun SDK yapılandırması](pushwoosh#sdk-configuration) sayfasına bakın.
```diff showLineNumbers
- let params = AdaptyProfileParameters.Builder()
- .with(pushwooshHWID: Pushwoosh.sharedInstance().getHWID())
- .build()
-
- Adapty.updateProfile(params: params) { error in
- // handle the error
- }
+ do {
+ try await Adapty.setIntegrationIdentifier(
+ key: "pushwoosh_hwid",
+ value: Pushwoosh.sharedInstance().getHWID()
+ )
+ } catch {
+ // handle the error
+ }
```
## Observer mode implementasyonunu güncelleme \{#update-observer-mode-implementation\}
Paywall'ları işlemlerle nasıl ilişkilendirdiğinizi güncelleyin. Önceden, `variationId` atamak için `setVariationId` metodunu kullanıyordunuz. Artık `variationId`'yi, yeni `reportTransaction` metodunu kullanarak işlemi kaydederken doğrudan ekleyebilirsiniz. Nihai kod örneğine [Observer mode'da paywall'ları satın alma işlemleriyle ilişkilendirme](report-transactions-observer-mode) bölümünden bakabilirsiniz.
:::warning
İşlemi `reportTransaction` metoduyla kaydetmeyi unutmayın. Bu adımı atlarsanız Adapty işlemi tanımaz, access level vermez, analitiklere eklemez veya entegrasyonlara göndermez. Bu adım zorunludur!
:::
```diff showLineNumbers
- let variationId = paywall.variationId
-
- // There are two overloads: for StoreKit 1 and StoreKit 2
- Adapty.setVariationId(variationId, forPurchasedTransaction: transaction) { error in
- if error == nil {
- // successful binding
- }
- }
+ do {
+ // every time when calling transaction.finish()
+ try await Adapty.reportTransaction(transaction, withVariationId: )
+ } catch {
+ // handle the error
+ }
```
---
# File: migration-to-ios-sdk-v3
---
---
title: "Adapty iOS SDK'yı v3.0'a Geçirme"
description: "Daha iyi performans ve yeni para kazanma özellikleri için Adapty iOS SDK v3.0'a geçiş yapın."
---
Adapty SDK v3.0, yeni nesil [Adapty Paywall Builder](adapty-paywall-builder)'ı destekler; bu, paywall oluşturmak için tasarlanmış, kod gerektirmeyen kullanıcı dostu aracın yeni sürümüdür. Maksimum esnekliği ve zengin tasarım özellikleriyle paywalllarınız çok daha etkili ve kârlı hale gelecektir.
:::info
AdaptyUI kütüphanesinin artık kullanımdan kaldırıldığını ve AdaptySDK'nın bir parçası olarak dahil edildiğini lütfen unutmayın.
:::
## Adapty SDK v3.x'i Swift Package Manager ile Yeniden Yükleme \{#reinstall-adapty-sdk-v3x-via-swift-package-manager\}
1. AdaptyUI SDK paket bağımlılığını projenizden silin, artık ihtiyacınız olmayacak.
2. Adapty SDK bağımlılığını zaten eklemiş olsanız da yeniden eklemeniz gerekecek. Bunun için Xcode'da **File** -> **Add Package Dependency...** yolunu izleyin. Paket bağımlılığı ekleme yöntemi Xcode sürümüne göre farklılık gösterebilir. Gerekirse Xcode belgelerine başvurun.
3. Depo URL'sini girin: `https://github.com/adaptyteam/AdaptySDK-iOS.git`
4. Sürümü seçin ve **Add package** düğmesine tıklayın.
5. İhtiyacınız olan modülleri seçin:
1. **Adapty** zorunlu modüldür
2. **AdaptyUI**, [Adapty Paywall Builder](adapty-paywall-builder) kullanmayı planlıyorsanız ihtiyaç duyacağınız isteğe bağlı modüldür.
6. Xcode paketi projenize ekleyecek ve içe aktarabileceksiniz. Bunun için **Choose Package Products** penceresinde **Add package** düğmesine bir kez daha tıklayın. Paket, **Packages** listesinde görünecektir.
## CocoaPods ile Adapty SDK v3.x'i Yeniden Yükleme \{#reinstall-adapty-sdk-v3x-via-cocoapods\}
1. `Podfile` dosyanıza Adapty'yi ekleyin. İhtiyacınız olan modülleri seçin:
1. **Adapty** zorunlu modüldür.
2. **AdaptyUI**, [Adapty Paywall Builder](adapty-paywall-builder) kullanmayı planlıyorsanız ihtiyaç duyacağınız isteğe bağlı modüldür.
2. ```shell showLineNumbers title="Podfile"
pod 'Adapty', '~> 3.2.0'
pod 'AdaptyUI', '~> 3.2.0' # optional module needed only for Paywall Builder
```
3. Çalıştırın:
```sh showLineNumbers title="Shell"
pod install
```
Bu işlem uygulamanız için bir `.xcworkspace` dosyası oluşturur. Uygulamanızın tüm geliştirme süreçlerinde bu dosyayı kullanın.
Adapty ve AdaptyUI SDK modüllerini etkinleştirin. v3.0 öncesinde AdaptyUI'yi etkinleştirmiyordunuz; **AdaptyUI aktivasyonunu eklemeyi** unutmayın. Parametreler değişmediğinden olduğu gibi bırakabilirsiniz.
```swift showLineNumbers
// In your AppDelegate class:
let configurationBuilder =
AdaptyConfiguration
.Builder(withAPIKey: "PUBLIC_SDK_KEY")
.with(observerMode: false)
.with(customerUserId: "YOUR_USER_ID")
.with(idfaCollectionDisabled: false)
.with(ipAddressCollectionDisabled: false)
Adapty.activate(with: configurationBuilder) { error in
// handle the error
}
// Only if you are going to use AdaptyUI
AdaptyUI.activate()
```
```swift title="" showLineNumbers
@main
struct SampleApp: App {
init()
let configurationBuilder =
AdaptyConfiguration
.Builder(withAPIKey: "PUBLIC_SDK_KEY")
.with(observerMode: false) // optional
.with(customerUserId: "YOUR_USER_ID") // optional
.with(idfaCollectionDisabled: false) // optional
.with(ipAddressCollectionDisabled: false) // optional
Adapty.activate(with: configurationBuilder) { error in
// handle the error
}
// Only if you are going to use AdaptyUI
AdaptyUI.activate()
}
var body: some Scene {
WindowGroup {
ContentView()
}
}
}
```
---
# End of Documentation
_Generated on: 2026-07-24T13:02:34.349Z_
_Successfully processed: 44/44 files_