SwiftyAds 16.0.0

SwiftyAds 16.0.0

Dominik Ringler 维护。



SwiftyAds 16.0.0

  • Dominik Ringler

Swift 5.0 Platform SPM supported CocoaPods Compatible

SwiftyAds

一个 Swift 库,用于显示横幅、插屏、激励视频和原生广告,由 Google AdMob 和支持的介质合作伙伴提供。

要求

  • iOS 13.0+
  • Swift 5.6+

创建账户

AdMob

注册 AdMob 账户 并为你要显示的广告类型创建所需的 AdUnitIDs。

资金选择(可选)

SwifyAds 使用 Google 的 用户消息平台 (UMP) SDK 来处理需要时的用户同意。此 SDK 可以处理 GDPR (EEA) 请求,也可以处理 iOS 14 ATT 提醒。

如果你想禁用用户同意请求,可以跳过此步骤,请参阅下文 用法部分 中的 Add SwiftyAds.plist 部分。否则,请阅读资金选择的 文档,确保它们正确设置以满足你的需求。

注意:苹果可能会拒绝使用 UMP SDK 来显示 iOS 14 ATT 提醒的应用程序。作为替代方案,你可能需要调整 解释消息 的措辞,或者你可以在配置 SwiftyAds 之前手动显示 ATT 提醒。

安装

Swift 包管理器

Swift 包管理器是一个用于自动化 Swift 代码分发工具,并集成到 swift 编译器中。

要将 swift 包添加到您的项目中,请打开您的项目到 xCode,然后点击 File > Swift Packages > Add Package Dependency。接着输入 https://github.com/crashoverride777/swifty-ads.git 作为代码库 URL 并完成安装向导。

或者,如果您有其他需要 SwiftyAds 作为依赖项的 swift 包,将其添加到 Package.swift 的依赖项值中同样简单。

dependencies: [
.package(url: "https://github.com/crashoverride777/swifty-ads.git", from: "14.0.0")
]

Cocoa Pods

Cocoa Pods 是 Cocoa 项目的依赖管理器。只需将以下行添加到您的 pod 文件中,即可简单安装 pod。

pod 'SwiftyAds'

手动安装

您还可以将 Sources 文件夹及其包含的文件复制到您的项目中,并安装所需的依赖。

使用前准备

更新 Info.plist

添加 SwiftyAds.plist

下载 模板 plist 并将其添加到您的项目主包中。然后输入所需广告单位 ID 和其他所需字段。所有条目均为可选项,如不需要,则可删除。

  • bannerAdUnitId (String)
  • interstitialAdUnitId (String)
  • rewardedAdUnitId (String)
  • rewardedInterstitialAdUnitId (String)
  • nativeAdUnitId (String)
  • 是否标记为儿童导向治疗方法(布尔值)(COPPA
  • 是否标记为未满同意年龄(布尔值)(GDPR
  • isUMPDisabled(布尔值)

注意:将isUMPDisabled条目添加并设置其值为true意味着SwiftyAds不会使用用户消息平台(UMP)SDK执行任何同意请求。在这种情况下,如果需要,您必须手动支持GDPR(EEA)和ATT(苹果)提醒。

链接AppTrackingTransparency框架

链接在常规选项卡下的“框架、库和嵌入式内容”中链接AppTrackingTransparency框架,否则iOS 14 ATT提醒将不会显示。

如果您还支持iOS 13及以下版本,您还必须在BuildPhases->Link Binary With Libraries中将其设置为可选,以避免崩溃。

使用方法

添加导入(CocoaPods或SwiftPackageManager)

  • 如果您通过CocoaPods或SwiftPackageManager安装,请将导入语句添加到您的swift文件(们)中。
import SwiftyAds

使用 GADRequest 构建器

创建一个实现 SwiftyAdsRequestBuilderType 协议的 SwiftyAdsRequestBuilder 类,SwiftyAds 将使用该类来加载广告。一些第三方网络,如 Vungle,可能需要特定的 GADRequest 额外参数。请查阅 AdMob 中介 文档

import SwiftyAds
import GoogleMobileAds

final class SwiftyAdsRequestBuilder {}

extension SwiftyAdsRequestBuilder: SwiftyAdsRequestBuilderType {

    func build() -> GADRequest {
        GADRequest()
    }
}

创建中介配置器(可选)

创建一个实现 SwiftyAdsMediationConfiguratorType 协议的 SwiftyAdsMediationConfigurator 类,用于管理 COPPA/GDPR 免责声明状态变更时的中介网络更新。请查阅 AdMob 中介 文档

App Lovin 示例

import SwiftyAds
import AppLovinAdapter

final class SwiftyAdsMediationConfigurator {}

extension SwiftyAdsMediationConfigurator: SwiftyAdsMediationConfiguratorType {

    func updateCOPPA(isTaggedForChildDirectedTreatment: Bool)
        // App Lovin mediation network example
        ALPrivacySettings.setIsAgeRestrictedUser(isTaggedForChildDirectedTreatment)
    }

    func updateGDPR(for consentStatus: SwiftyAdsConsentStatus, isTaggedForUnderAgeOfConsent: Bool) {
        // App Lovin mediation network example
        ALPrivacySettings.setHasUserConsent(consentStatus == .obtained)
        if !ALPrivacySettings.isAgeRestrictedUser() { // skip if already age restricted e.g. enableCOPPA called
            ALPrivacySettings.setIsAgeRestrictedUser(isTaggedForUnderAgeOfConsent)
        }
    }
}

配置

创建并调用配置方法,最好是在应用程序启动时完成,例如在 AppDelegate 的 didFinishLaunchingWithOptions 中。这也会触发初始的免责声明流程(除非已禁用)。只有在调用 completion 处理器后,才可显示广告。

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
    if let rootViewController = window?.rootViewController {
        configureSwiftyAds(from: rootViewController)
    }
    return true
}

private func configureSwiftyAds(from viewController: UIViewController) {
    #if DEBUG
    // testDeviceIdentifiers: The test device identifiers used for debugging purposes.
    // consentConfiguration: The debug consent configuration:
    //    1) .default(geography: UMPDebugGeography), 
    //    2) .resetOnLaunch(geography: UMPDebugGeography) 
    //    3) .disabled
        
    let environment: SwiftyAdsEnvironment = .development(testDeviceIdentifiers: [], consentConfiguration: .resetOnLaunch(geography: .EEA))
    #else
    let environment: SwiftyAdsEnvironment = .production
    #endif
    
    SwiftyAds.shared.configure(
        from: viewController,
        for: environment,
        requestBuilder: SwiftyAdsRequestBuilder(),
        mediationConfigurator: SwiftyAdsMediationConfigurator(), // set to nil if no mediation is required
        consentStatusDidChange: { status in
            print("The consent status has changed")
        },
        completion: { result in
            switch result {
            case .success(let consentStatus):
                print("Configure successful")
                // Ads will preload and sohuld be ready for displaying
            case .failure(let error):
                print("Setup error: \(error)")
            }
        }
    )
}

注意:如果您不使用 Google UMP SDK 来显示 iOS 14 应用跟踪透明度 (ATT) 提醒,请在配置 SwiftyAds 之前请求权限。

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
    if let rootViewController = window?.rootViewController {
        if  #available(iOS 14, *)  {
            ATTrackingManager.requestTrackingAuthorization { status in
                self.configureSwiftyAds(from: rootViewController)
            }
        } else {
            configureSwiftyAds(from: rootViewController)
        }
    }
    return true
}

在UIViewController外部展示广告

SwiftyAds需要引用一个UIViewController来展示广告。如果你不在一个ViewController中使用SwiftyAds,你可以按以下步骤获取rootViewController的引用。

AppDelegate

if let viewController = window?.rootViewController {
    SwiftyAds.shared.show(...)
}

SKScene

if let viewController = view?.window?.rootViewController {
    SwiftyAds.shared.show(...)
}

横幅广告

在你的UIViewController中为要显示的广告创建一个属性。

class SomeViewController: UIViewController {

    private var bannerAd: SwiftyAdsBannerType?
}

viewDidLoad中准备横幅广告。

override func viewDidLoad() {
    super.viewDidLoad()
    
    bannerAd = SwiftyAds.shared.makeBannerAd(
        in: self,
        adUnitIdType: .plist, // set to `.custom("AdUnitId")` to add a different AdUnitId for this particular banner ad
        position: .bottom(isUsingSafeArea: true) // banner is pinned to bottom and follows the safe area layout guide
        animation: .slide(duration: 1.5),
        onOpen: {
            print("SwiftyAds banner ad did receive ad and was opened")
        },
        onClose: {
            print("SwiftyAds banner ad did close")
        },
        onError: { error in
            print("SwiftyAds banner ad error \(error)")
        },
        onWillPresentScreen: {
            print("SwiftyAds banner ad was tapped and is about to present screen")
        },
        onWillDismissScreen: {
            print("SwiftyAds banner ad presented screen is about to be dismissed")
        },
        onDidDismissScreen: {
            print("SwiftyAds banner did dismiss presented screen")
        }
    )
}

并在viewDidAppear中显示它。这是为了确保视图已被正确布局,且具有有效的安全区域。

override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)
    
    bannerAd?.show(isLandscape: view.frame.width > view.frame.height)
}

要处理方向变化,只需在viewWillTransition中再次调用显示方法。

override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
    super.viewWillTransition(to: size, with: coordinator)
    
    coordinator.animate(alongsideTransition: { [weak self] _ in
        self?.bannerAd?.show(isLandscape: size.width > size.height)
    })
}

你可以通过调用hide方法来隐藏横幅。

bannerAd?.hide() 

你可以通过调用remove方法从父视图中移除横幅,之后将其引用设为nil。

bannerAd?.remove() 
bannerAd = nil

插屏广告

SwiftyAds.shared.showInterstitialAd(
    from: self,
    afterInterval: 2, // every 2nd time method is called ad will be displayed. Set to nil to always display.
    onOpen: {
        print("SwiftyAds interstitial ad did open")
    },
    onClose: {
        print("SwiftyAds interstitial ad did close")
    },
    onError: { error in
        print("SwiftyAds interstitial ad error \(error)")
    }
)

奖励型广告

奖励型广告可能是不可跳过的,并且只能当按下专用按钮时展示。

SwiftyAds.shared.showRewardedAd(
    from: self,
    onOpen: {
        print("SwiftyAds rewarded ad did open")
    },
    onClose: {
        print("SwiftyAds rewarded ad did close")
    }, 
    onError: { error in
        print("SwiftyAds rewarded ad error \(error)")
    },
    onNotReady: { [weak self] in
        guard let self = self else { return }
        print("SwiftyAds rewarded ad was not ready")
        
        // If the user presses the rewarded video button and watches a video it might take a few seconds for the next video to reload.
        // Use this callback to display an alert incase the video was not ready. 
        let alertController = UIAlertController(
            title: "Sorry",
            message: "No video available to watch at the moment.",
            preferredStyle: .alert
        )
        alertController.addAction(UIAlertAction(title: "Ok", style: .cancel))
        DispatchQueue.main.async {
            self.present(alertController, animated: true)
        }
    },
    onReward: { [weak self] rewardAmount in
        print("SwiftyAds rewarded ad did reward user with \(rewardAmount)")
        // Provide the user with the reward e.g coins, diamonds etc
    }
)

注意:AdMob 提供了一个新的奖励视频 API,允许您预加载具有不同 AdUnitIDs 的多个奖励视频。虽然 SwiftyAds 使用了新的 API,但目前它一次只能加载一个奖励广告。

奖励横幅广告

奖励横幅广告可以在您的应用程序流程中自然呈现,类似于横幅广告,并且不需要像常规奖励广告那样使用专用按钮。在显示奖励横幅广告之前,您必须向用户展示一个介绍屏幕,该屏幕提供清晰的奖励说明和选项,在广告开始之前可以跳过广告。

SwiftyAds.shared.showRewardedInterstitialAd(
    from: self,
    afterInterval: 2, // every 2nd time method is called ad will be displayed. Set to nil to always display.
    onOpen: {
        print("SwiftyAds rewarded interstitial ad did open")
    },
    onClose: {
        print("SwiftyAds rewarded interstitial ad did close")
    }, 
    onError: { error in
        print("SwiftyAds rewarded interstitial ad error \(error)")
    },
    onReward: { [weak self] rewardAmount in
        print("SwiftyAds rewarded interstitial ad did reward user with \(rewardAmount)")
        // Provide the user with the reward e.g coins, diamonds etc
    }
)

原生广告

要展示原生广告,请调用加载方法。一旦收到原生广告,您可以使用原生广告内容更新您的自定义广告视图。

您可以通过 loaderOptions 参数设置要加载的广告数量(GADMultipleAdsAdLoaderOptions)。设置为 .single 以使用默认选项。

根据谷歌的文档,对于已配置为调优的 AdMob 广告单元 ID,目前无法对多个原生广告进行请求。使用调优的出版商应避免在请求时使用 GADMultipleAdsAdLoaderOptions 类。在这种情况下,您还可以将 loaderOptions 参数设置为 .single

SwiftyAds.shared.loadNativeAd(
    from: self,
    adUnitIdType: .plist, // set to `.custom("AdUnitId")` to add a different AdUnitId for this particular native ad
    loaderOptions: .single, // set to `.multiple(2)` to load multiple ads for example 2
    onFinishLoading: {
        // Native ad has finished loading and new ads can now be loaded
    },
    onError: { error in
        // Native ad could not load ad due to error
    },
    onReceive: { nativeAd in
        // show native ad (see demo app or google documentation)
    }
)

注意:尽管预加载广告是一种很好的技术,但您很重要,不要永久保留旧的原生广告而不显示它们。任何在超过一小时后未显示的原生广告对象都应被丢弃,并用新的请求的新广告替换。

错误

您可以使用 SwiftyAdsError 枚举来处理 SwiftyAds 特定错误。

if let swiftyAdsError = error as? SwiftyAdsError {
    switch swiftyAdsError { 
    case .interstitialAdNotLoaded:
        // Ad was not loaded
    default:
        break
    }
}

同意状态

// Check current consent status
SwiftyAds.shared.consentStatus

布尔值

// Check if interstitial ad is ready, for example to show an alternative ad
SwiftyAds.shared.isInterstitialAdReady

// Check if rewarded ad is ready, for example to show/hide button
SwiftyAds.shared.isRewardedAdReady

// Check if rewarded interstitial ad is ready, for example to show an alternative ad
SwiftyAds.shared.isRewardedInterstitialAdReady

// Check if child directed treatment is tagged on/off. Nil if not indicated how to be treated. (COPPA)
SwiftyAds.shared.isTaggedForChildDirectedTreatment

// Check if under age of consent is tagged on/off (GDPR)
SwiftyAds.shared.isTaggedForUnderAgeOfConsent

// Check if ads have been disabled
SwiftyAds.shared.isDisabled

禁用/启用应用内购买广告

调用 disable(_ isDisabled: Bool) 方法后,横幅广告、插页式广告和激励式插页式广告将不再显示。这不会阻止正常显示的激励式广告,因为它们应该有一个专门的按钮。这样您可以删除横幅广告、插页式广告和激励式插页式广告,但仍可显示激励式广告。

SwiftyAds.shared.setDisabled(true)

对于永久存储,您需要创建自己的布尔逻辑并将它保存在类似 NSUserDefaults 的地方,或者最好保存在 Keychain 中。然后在应用启动时,在调用 SwiftyAds.shared.configure(...) 之前,检查您保存的布尔值,并在必要时禁用广告。

if UserDefaults.standard.bool(forKey: "RemovedAdsKey") == true {
    SwiftyAds.shared.setDisabled(true)
}

再次请求同意

必须允许用户更改他们的GDPR同意设置,通常通过设置中的按钮。

func consentButtonPressed() {
    SwiftyAds.shared.askForConsent(from: self) { result in
        switch result {
        case .success(let status):
            print("Did change consent status")
        case .failure(let error):
            print("Consent status change error \(error)")
        }
    }
}

如果不需要同意或用户为未成年用户,可以从隐藏同意按钮。

// If consent is not required e.g. outside EEA than we do not need to show consent button.
// If inside EEA we need to display the consentButton unless user is tagged for under age of consent
if SwiftyAds.shared.consentStatus == .notRequired {
    consentButton.isHidden = true
} else {
    consentButton.isHidden = SwiftyAds.shared.isTaggedForUnderAgeOfConsent
}

App Store 发布信息

确保为 Apple App Store 数据披露要求做好准备

演示

https://github.com/crashoverride777/swifty-ads-demo

许可协议

SwiftyAds 在 MIT 许可下发布。查看 LICENSE 详细信息