# iOS 奖励广告服务集成

> 通过初始化广告单元、设置委托和处理广告事件，在 iOS app 中实现奖励视频广告单元。

Unity LevelPlay Rewarded 是一个全屏广告单元，通常在 app 生命周期中的自然过渡点投放。 

> **Note:**
>
> 本文档与 SDK 8.5.0+ 相关。

## 先决条件##prerequisites

* 确保已将 LevelPlay SDK 正确集成到应用程序中。[此处](/grow/levelplay/sdk/ios/sdk-integration.md)概述了集成。
* 确保使用 LevelPlay Initialization API 初始化 SDK。
* 在 LevelPlay 后台中找到 AdUnitID。

## 创建奖励广告对象##create-rewarded-ad-object

必须在收到 **onInitSuccess** 回调后执行奖励广告对象的创建。

该对象是可重用的实例，可以处理多个加载并在整个会话中显示。创建后，应将其用于加载和展示同一广告单元的广告服务。

对于更高级的实现，如果需要，可以创建多个奖励广告对象。

1. **Objective-C**

   ```objective-c
   self.rewardedAd = [[LPMRewardedAd alloc] initWithAdUnitId:@"adUnitId"];	 
   ```

2. **Swift**

   ```swift
   self.rewardedAd = LPMRewardedAd(adUnitId: "adUnitId")
   ```

## 实现委托##implement-delegates

在代码中实现 **LPMRewardedAdDelegate** 以获取广告投放信息。 

* 建议在加载奖励广告之前设置委托。
* 每个奖励广告都应有自己的委托实现。
* 委托方法在主线程上运行。

1. **Objective-C**

   ```objective-c
   self.rewardedAd = [[LPMRewardedAd alloc] initWithAdUnitId:@"adUnitId"]; 
   self.rewardedAd.delegate = self;

   #pragma mark - LPMRewardedAdDelegate Methods
   - (void)didLoadAdWithAdInfo:(LPMAdInfo *)adInfo {}
   - (void)didFailToLoadAdWithAdUnitId:(NSString *)adUnitId error:(NSError *)error {}
   - (void)didChangeAdInfo:(LPMAdInfo *)adInfo {}
   - (void)didDisplayAdWithAdInfo:(LPMAdInfo *)adInfo {
   - (void)didFailToDisplayAdWithAdInfo：(LPMAdInfo *)adInfo 报错：(NSError *)报错 {
   - (void)didClickAdWithAdInfo:(LPMAdInfo *)adInfo {}
   - (void)didCloseAdWithAdInfo:(LPMAdInfo *)adInfo {}
   - (void)didRewardAdWithAdInfo：(LPMAdInfo *)adInfo 奖励：(LPMReward *)奖励{
   ```

2. **Swift**

   ```swift
   self.rewardedAd = LPMRewardedAd(adUnitId: "adUnitId") 
   self.rewardedAd.setDelegate(self)

   // MARK: LPMRewardedAdDelegate methods
   func didLoadAd（包含 adInfo：LPMAdInfo) {
   func didFailToLoadAd(withAdUnitId adUnitId：字符串，报错：报错) {
   func didChangeAdInfo(_ adInfo：LPMAdInfo) {
   func didDisplayAd（包含 adInfo：LPMAdInfo) {
   func didFailToDisplayAd（包含 adInfo：LPMAdInfo，报错：报错) {
   func didClickAd（包含 adInfo：LPMAdInfo) {
   func didCloseAd（包含 adInfo：LPMAdInfo) {
   func didRewardAd（包含 adInfo：LPMAdInfo，奖励：LPMReward) {
   ```

### LevelPlay 广告信息##levelplay-ad-info

**LPMAdInfo** 参数包含有关加载的广告的信息。
在[此处](/grow/levelplay/sdk/ios/levelplay-listener-adinfo-integration.md)了解有关 LPMAdInfo 实现和可用字段的更多信息。

## 获取奖励广告详细信息##get-rewarded-ad-details

使用 getReward API 可以访问您在 LevelPlay 后台中设置的奖励数据。与其他聚合 API 不同，这是一个独立调用，在初始化后返回存储在 SDK 本地的数据。这使您能够构建动态、数据驱动的 UI，在用户参与广告之前告知他们潜在的奖励，从而无需在app中硬编码奖励值。

### 先决条件##prerequisites

在实现 getReward API 之前，请确保项目满足以下技术要求：

* **SDK 初始化**：调用 initSDK 并等待 onInitializationSuccess 回调以确保奖励数据已缓存。
* **广告对象实例**：在调用 API 之前，使用有效的 Ad Unit ID 实例化奖励广告对象。
* **最低 SDK 版本**：使用 LevelPlay SDK 8.1.0 或更高版本（原生或 Unity 软件包）。

### 最佳实践##best-practices

遵循这些建议可确保稳定且可预测的集成。

* **初始化成功时调用**：调用 getReward 的最佳时间是初始化成功监听器器内部。这样可以确保 UI 在用户进入屏幕时就绪。
* **检查空状态**：在更新 UI 之前，请始终验证该数量> 0。如果在初始化期间发生网络报错，这将确保平滑的用户体验。
* **放置/位置精度**：确保在 getReward("placementName") 中使用的字符串与 LevelPlay 后台中定义的名称完全匹配。

### API 结构##api-structure

getReward 方法允许您从 LevelPlay 后台访问同步的奖励数据。使用此方法可以查询本地 SDK 缓存中指定的广告放置/位置或全局广告单元默认值。

#### getReward##getreward

```objective-c
- (LPMReward *)getRewardWithPlacementName:(NSString *)placementName;
```

获取指定的广告放置/位置或默认广告单元的奖励名称和金额。没有其他参数可以使用。

| 参数            | 描述                                                   |
| ------------- | ---------------------------------------------------- |
| placementName | 在 LevelPlay 后台中定义的放置/位置的唯一标识符。通道`nil`，用于获取广告单元的默认奖励。 |

返回包含名称（字符串）和数量（int）的 LPMReward 对象。

### 初始设置##initial-setup

getReward API 充当 LevelPlay SDK 的核心组件，在如下逻辑下运行以确保数据无延迟可用：

* **集成功能**：由于奖励数据是在初始 SDK 设置期间获取的，因此 API 调用是即时的，不需要网络请求。
* **编辑器配置**：将 app 与 LevelPlay SDK 集成后，API 可以立即使用。测试此功能不需要额外的资源或插件。

### 了解奖励选择逻辑##understand-reward-selection-logic

API 根据指定的层级视图返回 LPMReward 对象。了解此逻辑有助于排除出现指定的奖励的原因。

* **放置/位置级别**：如果在调用中提供了有效的广告放置/位置称，SDK 将返回控制面板中为该广告位放置/位置的指定的奖励。
* **广告单元级别**：如果广告放置/位置名称为零或未找到，SDK 将回退到为广告单元定义的默认奖励。
* **回退状态**：如果在初始化完成之前调用 API，则返回一个字符串名称为空且值为 0 的奖励对象。

### 动态更新 UI##update-your-ui-dynamically

使用 getReward API 可将静态按钮变换为高意图的行动调用。例如：您可以显示“Watch to earn 50 Gold”，而不是通用的“Watch Video”按钮。

* **有效金额**：在更新 UI 组件之前，请务必验证 reward.amount > 0。
* **事件驱动更新**：在初始化成功监听器器中调用 API 以确保 UI 在用户进入屏幕时准确无误。
* **区分大小写**：确保代码中的放置/位置名称字符串与 LevelPlay 后台完全匹配；不匹配的字符串将触发器广告单元回退。

### 获取奖励数据示例##retrieve-reward-data-examples

以下示例展示了如何调用 iOS 奖励 API：

1. **Objective-C**

   ```objective-c
   /** 
    * 获取与广告关联的奖励。
    * 使用此方法可获得为广告单元或放置/位置配置的奖励。的 
    * 当有效的放置/位置名称时，指定的放置/位置奖励优先于广告单元奖励 
    * 提供。
    * @param放置/位置 要获取奖励的放置/位置名称，或使用广告单元奖励的`nil`。
    * @return A `LPMReward` 对象。失败时返回空奖励（`name: ""` 和 `amount: 0`）。
    */ 
   LPMReward *reward = [self.rewardedAd getRewardWithPlacementName:@"main_menu"];
   NSLog(@"Reward:%ld %@", (long)reward.amount, reward.name);
   ```

2. **Swift**

   ```swift
   /** 
    * 获取与广告关联的奖励。
    * 使用此方法可获得为广告单元或放置/位置配置的奖励。的 
    * 当有效的放置/位置名称时，指定的放置/位置奖励优先于广告单元奖励 
    * 提供。
    * @param placementName 要获取奖励的放置/位置名称，或使用广告单元奖励的`nil`。
    * @return A `LPMReward` 对象。失败时返回空奖励（`name: ""` 和 `amount: 0`）。
    */ 
   let reward = self.rewardedAd.getReward(placementName: "main_menu")
   print("Watch to get \(reward.amount) \(reward.name)")
   ```

### getReward API 实现故障排除##troubleshooting-getreward-api-implementation

* **奖励金额返回 0**：如果在 onInitializationSuccess 回调之前调用 API，通常会发生这种情况。在查询奖励之前，请确保 SDK 完全准备就绪。
* **显示错误奖励类型**：检查是否有多个广告位。如果放置/位置名称拼写错误，SDK 默认认为主广告单元奖励，而不是指定的广告放置/位置奖励。

## 加载奖励广告##load-rewarded-ad

要加载奖励广告，请使用 **loadAd**。

1. **Objective-C**

   ```objective-c
   [self.rewardedAd loadAd];
   ```

2. **Swift**

   ```swift
   self.rewardedAd.loadAd()	 
   ```

## 显示奖励广告##show-rewarded-ad

在收到 **didLoadAd** 回调后显示奖励广告。

* 需要共享 **ViewController**。 
* 如果使用放置，请在 **showAd** API 中通道放置/位置名称，如下文 Placements 部分所示。
* 广告成功展示给用户后，可以通过重复加载步骤加载另一个广告。 

1. **Objective-C**

   ```objective-c
   - (void)showRewardedAd {
       // 检查广告是否已准备就绪
       if ([self.rewardedAd isAdReady]) {
           // 显示而不放置/位置
           [self.rewardedAd showAdWithViewController:self placementName:NULL];
       }
   }	 
   ```

2. **Swift**

   ```swift
   func showRewardedAd() {
       // 检查广告是否已准备就绪  
       if self.rewardedAd.isAdReady() {
           // 显示而不放置/位置
           self.rewardedAd.showAd(viewController: self, placementName: nil)
       }
   }	 
   ```

### 检查 Ad is Ready##check-ad-is-ready

为了避免展示失败，并确保广告可以正确展示，建议在调用 **showAd** API 之前使用以下 API。

**isAdReady** – 如果广告已成功加载且广告单元未设置上限，则返回 true，否则返回 false。

**isPlacementCapped** – 有效放置/位置被限制时返回 true。如果放置/位置无效或未设置上限，此 API 将返回 false。

1. **Objective-C**

   ```objective-c
   // 检查广告是否已准备就绪并且放置/位置未设置上限 
   if ([self.rewardedAd isAdReady] &amp;&amp; ![LPMRewardedAd isPlacementCapped:placementName]) {
       [self.rewardedAd showAdWithViewController:self placementName:placementName];
   }
   ```

2. **Swift**

   ```swift
   // 检查广告是否已准备就绪并且放置/位置未设置上限 
   if self.rewardedAd.isAdReady(), !LPMRewardedAd.isPlacementCapped(placementName) {
       self.rewardedAd.showAd(viewController: self, placementName: placementName)
   }	 
   ```

### 广告位##placements

我们支持 LevelPlay 后台上的 Rewarded [广告位](/grow/levelplay/platform/settings/placements.md)节奏和上限。 

如果为奖励广告服务设置了放置位置，请调用 **showAd** 方法为指定的放置/位置提供广告。

1. **Objective-C**

   ```objectivec
   // 检查广告是否已准备就绪并且放置/位置未设置上限
   if ([self.rewardedAd isAdReady] &amp;&amp; ![LPMRewardedAd isPlacementCapped:placementName]) {
       // 显示带有放置/位置的广告
       [self.rewardedAd showAdWithViewController:self placementName:@"PlacementName"];
   }	 
   ```

2. **Swift**

   ```swift
   // 检查广告是否已准备就绪并且放置/位置未设置上限 
   if self.rewardedAd.isAdReady(), !LPMRewardedAd.isPlacementCapped(placementName) {
       // 显示带有放置/位置的广告
       self.rewardedAd.showAd(viewController: self, placementName: placementName) 
   }	 
   ```

### 动态 UserId##dynamic-userid

动态 UserID 是一个参数，用于验证可在整个会话中更改的 AdRewarded 交易。您将通过[服务器到服务器](/grow/levelplay/platform/settings/server-to-server-callback.md)的广告奖励回调收到此参数，必须在调用 showAd 之前设置此参数。

* 字字符串必须包含 1-64 个字母数字角色。
* 您将在回调网址中收到一个 `dynamicUserId` 参数以及奖励详细信息。

1. **Objective-C**

   ```objective-c
   [LevelPlay setDynamicUserId:@"userId"];
   ```

2. **Swift**

   ```swift
   LevelPlay.setDynamicUserId("userId")
   ```

## 奖励广告服务的完整实现示例##full-implementation-example-of-rewarded-ads

1. **Objective-C**

   ```objective-c
   NS_ASSUME_NONNULL_BEGIN
   @interface RewardedAdViewController () <LPMRewardedAdDelegate>
   @property(nonatomic, strong) LPMRewardedAd *rewardedAd;
   @end
   @implementation RewardedAdViewController
   - (void)createRewardedAd {
       self.rewardedAd = [[LPMRewardedAd alloc] initWithAdUnitId:@"adUnitId"];
       self.rewardedAd.delegate = self;
   }
   - (void)loadRewardedAd {
       // 用于加载或重新加载广告
       [self.rewardedAd loadAd];
   }
   - (void)showRewardedAd {
       if ([self.rewardedAd isAdReady]) {
       [self.rewardedAd showAdWithViewController:self placementName:NULL];
     }
   }
   - (void)showRewardedAdWithPlacementName:(NSString *)placementName { }
       // 检查广告是否已准备就绪并且放置/位置未设置上限 
       if ([self.rewardedAd isAdReady] &amp;&amp; ![LPMRewardedAd isPlacementCapped:placementName]) {
           [self.rewardedAd showAdWithViewController:self placementName:placementName];
       }
   }
   #pragma mark - LPMRewardedAdDelegate 方法
   - (void)didLoadAdWithAdInfo:(LPMAdInfo *)adInfo {}
   - (void)didFailToLoadAdWithAdUnitId:(NSString *)adUnitId error:(NSError *)error {}
   - (void)didChangeAdInfo:(LPMAdInfo *)adInfo {}
   - (void)didDisplayAdWithAdInfo:(LPMAdInfo *)adInfo {
   - (void)didFailToDisplayAdWithAdInfo：(LPMAdInfo *)adInfo 报错：(NSError *)报错 {
   - (void)didClickAdWithAdInfo:(LPMAdInfo *)adInfo {}
   - (void)didCloseAdWithAdInfo:(LPMAdInfo *)adInfo {}
   - (void)didRewardAdWithAdInfo：(LPMAdInfo *)adInfo 奖励：(LPMReward *)奖励{ 
   @end
   NS_ASSUME_NONNULL_END
   ```

2. **Swift**

   ```swift
   类 RewardedAdViewController：UIViewController、LPMRewardedAdDelegate {
   var rewardAd：LPMRewardedAd!

   func createRewardedAd() {
       self.rewardedAd = LPMRewardedAd(adUnitId: "adUnitId")
       self.rewardedAd.setDelegate(self)
   }

   func loadRewardedAd() {
       // used to load or reload the ad
       self.rewardedAd.loadAd()
   }

   func showRewardedAd() {
       if self.rewardedAd.isAdReady() {
           self.rewardedAd.showAd(viewController: self, placementName: nil)
       }
   }

   func showRewardedAd(withPlacementName placementName:字符串) {
       // check that ad is ready and that the placement is not capped 
       if self.rewardedAd.isAdReady(), !LPMRewardedAd.isPlacementCapped(placementName) {
           self.rewardedAd.showAd(viewController: self, placementName: placementName)
       }
   }

   // MARK:LPMRewardedAdDelegate 方法
   func didLoadAd（包含 adInfo：LPMAdInfo) {
   func didFailToLoadAd(withAdUnitId adUnitId：字符串，报错：报错) {
   func didChangeAdInfo(_ adInfo：LPMAdInfo) {
   func didDisplayAd（包含 adInfo：LPMAdInfo) {
   func didFailToDisplayAd（包含 adInfo：LPMAdInfo，报错：报错) {
   func didClickAd（包含 adInfo：LPMAdInfo) {
   func didCloseAd（包含 adInfo：LPMAdInfo) {
   func didRewardAd（包含 adInfo：LPMAdInfo，奖励：LPMReward) { 
   }
   ```

## LevelPlay Mediation 演示应用程序##levelplay-mediation-demo-app

Integration Demo 应用程序演示如何在 app 中集成奖励广告单元 API。

[下载 iOS demo 应用程序](https://github.com/ironsource-mobile/Mediation-Demo-Apps)

验证您与我们的[集成测试套件](/grow/levelplay/sdk/ios/integration-test-suite.md)的集成。

## 后续步骤##next-steps

请遵循我们的集成指南来集成其他奖励广告网络或配置其他广告格式：

* [添加聚合网络](/grow/levelplay/sdk/ios/mediation-networks.md)
* [插页式广告服务](/grow/levelplay/sdk/ios/interstitial-integration.md)
* [横幅广告服务](/grow/levelplay/sdk/ios/banner-integration.md)
* [原生广告服务](/grow/levelplay/sdk/ios/native-ads-integration.md)
