iOS SDK
Integrate Appylar in your iOS app.
Applies to Appylar v1.0
The Appylar iOS SDK (v1.0.0) is the Swift equivalent of the Android SDK: request and display ads, and promote your app across the network through campaigns. It's a pure-Swift package with no third-party dependencies. This page covers the complete public API.
You need an app key (app_live_…) from the portal before you start. See Getting Started.
#Requirements
| Min iOS | 15.0 |
| Language | Swift 6, Xcode 16+ |
| Distribution | Swift Package Manager |
No Info.plist changes are required — the SDK does not use App Tracking Transparency or SKAdNetwork in v1.
#Installation
#Swift Package Manager
Add the package in Xcode (File → Add Package Dependencies) or in Package.swift:
dependencies: [
.package(url: "https://github.com/appylar/appylar-ios-sdk.git", from: "1.0.0"),
],
targets: [
.target(
name: "YourApp",
dependencies: [.product(name: "Appylar", package: "appylar-ios-sdk")]
),
]
#CocoaPods
A CocoaPods podspec ships in the repo, but the pod isn't published to the CocoaPods trunk yet. Use Swift Package Manager for now — the pod 'Appylar' install line will be documented here once it's live.
#initialize()
Call initialize once at app startup. It's non-blocking and idempotent.
import Appylar
Appylar.initialize(appKey: "app_live_xxx")
#Configuration
Appylar.initialize(
appKey: "app_live_xxx",
config: AppylarConfig(testMode: false, logLevel: .info)
)
testMode— sandbox with deterministic test ads. Defaultfalse.logLevel—.none,.error,.warn,.info(default) or.debug.
#Consent
Appylar.setConsent(Consent(gdprConsent: true, childDirected: false))
gdprConsent— consent for personalized advertising.childDirected— COPPA / families mode.
The SDK does not show a consent dialog — collect consent with your own CMP and pass the result to setConsent.
#Banner
BannerView is a UIView subclass. Add it to your view hierarchy and it loads itself once when it moves to a window — there's no load() call and no auto-refresh. The creative scales aspect-fit inside the view, so control the size with your own frame or Auto Layout constraints.
import Appylar
import UIKit
final class HomeViewController: UIViewController, BannerDelegate {
private var banner: BannerView?
override func viewDidLoad() {
super.viewDidLoad()
let banner = Appylar.bannerView()
banner.delegate = self
banner.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(banner)
NSLayoutConstraint.activate([
banner.leadingAnchor.constraint(equalTo: view.leadingAnchor),
banner.trailingAnchor.constraint(equalTo: view.trailingAnchor),
banner.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor),
banner.heightAnchor.constraint(equalToConstant: 50),
])
self.banner = banner
}
func bannerViewDidLoad(_ bannerView: BannerView) { }
func bannerView(_ bannerView: BannerView, didFailToLoad error: AdError) { }
}
Call banner.destroy() when you remove it; it won't reload afterward.
#Interstitial
import Appylar
import UIKit
final class GameViewController: UIViewController, InterstitialDelegate {
private var interstitial: Interstitial?
func preloadAd() {
let interstitial = Appylar.createInterstitial()
interstitial.delegate = self
interstitial.load()
self.interstitial = interstitial
}
func interstitialDidLoad(_ interstitial: Interstitial) {
interstitial.show(from: self)
}
func interstitial(_ interstitial: Interstitial, didFailToLoad error: AdError) { }
func interstitialDidShow(_ interstitial: Interstitial) { }
func interstitialDidDismiss(_ interstitial: Interstitial) { }
}
show(from:) presents a loaded ad from the given view controller. It's a no-op if nothing is loaded or one is already showing; showing in an invalid state delivers .invalidState.
#Delegates
Both delegate protocols have default (no-op) implementations, so you implement only what you need. All UI types are @MainActor; delegates are held weakly and callbacks arrive on the main actor.
| Delegate | Method | When |
|---|---|---|
BannerDelegate | bannerViewDidLoad(_:) | Banner loaded |
bannerView(_:didFailToLoad:) | Load failed | |
InterstitialDelegate | interstitialDidLoad(_:) | Ad ready |
interstitial(_:didFailToLoad:) | Load failed | |
interstitialDidShow(_:) | Ad presented | |
interstitialDidDismiss(_:) | Ad closed |
#Errors
Failures arrive through the didFailToLoad delegate methods. AdError has exactly four cases:
| Case | Meaning |
|---|---|
.noFill | No eligible ad right now — expected, not a bug |
.networkError | Network or server error |
.notInitialized | Appylar.initialize(appKey:) hasn't run, or the key is invalid |
.invalidState | e.g. showing an interstitial before a successful load |
#Lifecycle
Appylar.initialize(appKey:)once at startup;setConsentas early as possible.- Banner: create → set
delegate→ add to the view hierarchy (it self-loads) →destroy()on removal. - Interstitial:
createInterstitial()→ setdelegate→load()→show(from:)oninterstitialDidLoad.
One ad at a time; no preloading of multiple ads and no auto-refresh in v1.
#Sample app
Space Dash is a complete SwiftUI reference app built on this SDK — initialize, consent, a banner
and an interstitial, with real loading, loaded, no-fill and error states and correct lifecycle. It
uses only the public API and mirrors the Android sample. Find it under Examples/SpaceDash in the
iOS SDK repository.
#Best practices
- Initialize at launch so a token is ready before the first request.
- Keep a strong reference to interstitials until they're dismissed.
- Treat
.noFillas normal. - Use
.debuglogging during integration,.infoin production.
#Distribution store
The SDK reports its OS on every ad request, and Appylar routes each ad's click-through to the matching store listing — the App Store on iOS. iOS ships through a single store, so you rarely need to set this, but the option exists for parity across the SDKs:
Appylar.initialize(
appKey: "app_live_xxx",
config: AppylarConfig(store: .appleAppStore)
)
AppylarStore covers .googlePlay, .appleAppStore, .amazonAppstore, .huaweiAppGallery and .samsungGalaxyStore. See the serving protocol for how routing works.