> ## Documentation Index
> Fetch the complete documentation index at: https://docs.cloudx.io/llms.txt
> Use this file to discover all available pages before exploring further.

# 集成

> iOS SDK 完整集成指南

需要 iOS 13.0+、Xcode 16.0+ 和 Swift 6.0+。

## 安装

### CocoaPods

```ruby Podfile theme={null}
platform :ios, '13.0'

target 'YourApp' do
  use_frameworks!

  # 核心 SDK
  pod 'CloudXCore', '~> 3.5.0'

  # 广告网络适配器（根据需要添加）。
  # 每个适配器独立按 <网络 SDK 版本>.<适配器修订号> 版本化，
  # 并针对该确切网络 SDK 版本构建。
  pod 'CloudXMetaAdapter', '~> 6.21.1.0'            # FBAudienceNetwork 6.21.1
  pod 'CloudXVungleAdapter', '~> 7.7.4.0'           # VungleAds 7.7.4
  pod 'CloudXInMobiAdapter', '~> 11.3.0.0'          # InMobiSDK 11.3.0
  pod 'CloudXMintegralAdapter', '~> 8.1.5.0'        # MintegralAdSDK 8.1.5
  pod 'CloudXUnityAdsAdapter', '~> 4.19.0.0'        # UnityAds 4.19.0
  pod 'CloudXMagniteAdapterV2', '~> 1.0.0.1'        # MagniteSDK 1.0.0
  pod 'CloudXMobileFuseAdapter', '~> 1.11.0.0'      # MobileFuseSDK 1.11.0
  pod 'CloudXMolocoAdapter', '~> 4.8.0.0'           # MolocoSDKiOS 4.8.0
  pod 'CloudXVerveAdapter', '~> 3.9.0.0'            # HyBid 3.9.0
  pod 'CloudXDigitalTurbineAdapter', '~> 8.4.8.0'   # Fyber Marketplace SDK 8.4.8
  pod 'CloudXGoogleWaterfallAdapter', '~> 13.6.0.0' # Google Mobile Ads SDK 13.6.0
  pod 'CloudXPangleAdapter', '~> 7.9.1.3.0'         # Ads-Global（Pangle / 字节跳动）7.9.1.3
end
```

```bash theme={null}
pod install --repo-update
```

## 初始化

<CodeGroup>
  ```objc Objective-C theme={null}
  #import <CloudXCore/CloudXCore.h>

  CLXInitializationConfiguration *config =
      [CLXInitializationConfiguration configurationWithAppKey:@"your-app-key-here"];

  [[CloudXCore shared] initializeWithConfiguration:config completion:^(CLXSdkConfiguration *sdkConfig, CLXError * _Nullable error) {
      if (sdkConfig) {
          NSLog(@"CloudX SDK 初始化成功");
      } else {
          NSLog(@"CloudX SDK 初始化失败: %@", error.localizedDescription);
      }
  }];
  ```

  ```swift Swift theme={null}
  import CloudXCore

  let config = CLXInitializationConfiguration.configuration(appKey: "your-app-key-here", builderBlock: nil)

  CloudXCore.shared.initialize(with: config) { sdkConfig, error in
      if sdkConfig != nil {
          print("CloudX SDK 初始化成功")
      } else {
          print("CloudX SDK 初始化失败: \(error?.localizedDescription ?? "未知错误")")
      }
  }
  ```
</CodeGroup>

## 广告格式

CloudX 支持横幅、MREC、插屏、激励、原生和 App Open 广告集成。请使用对应广告格式指南查看实现细节：

<CardGroup cols={2}>
  <Card title="横幅和 MREC 广告" href="/zh/ios/ad-formats/banner-mrec">
    创建固定尺寸展示广告位，并可选择控制刷新。
  </Card>

  <Card title="插屏广告" href="/zh/ios/ad-formats/interstitial">
    加载和展示全屏插屏广告位。
  </Card>

  <Card title="原生广告" href="/zh/ios/ad-formats/native">
    渲染原生创意和 Reels 风格原生视频体验。
  </Card>

  <Card title="激励广告" href="/zh/ios/ad-formats/rewarded">
    在用户完成激励广告观看后发放奖励。
  </Card>

  <Card title="App Open 广告" href="/zh/ios/ad-formats/app-open">
    面向应用启动和回到前台时刻的全屏广告位。
  </Card>
</CardGroup>

### 广告信息 (CLXAd)

`CLXAd` 对象会传递给代理回调，包含已加载/展示广告的信息：

| 属性                   | 类型                                     | 描述                              |
| -------------------- | -------------------------------------- | ------------------------------- |
| `adFormat`           | `CLXAdFormat`                          | 广告格式（横幅、MREC、插屏、激励、原生）          |
| `adUnitId`           | `NSString?`                            | 广告单元 ID                         |
| `adUnitName`         | `NSString?`                            | 广告单元名称                          |
| `networkName`        | `NSString?`                            | 获胜广告网络的名称                       |
| `networkPlacement`   | `NSString?`                            | 网络特定的展示位置 ID                    |
| `placement`          | `NSString?`                            | 通过 `placement` 属性设置的自定义展示位置     |
| `revenue`            | `NSNumber?`                            | 展示级别收入（美元）                      |
| `revenuePrecision`   | `NSString?`                            | 获胜广告网络提供的收入精度                   |
| `creativeIdentifier` | `NSString?`                            | 用于素材级问题排查的素材标识符                 |
| `requestLatency`     | `NSTimeInterval`                       | 从广告请求到广告响应的耗时（秒）                |
| `nativeAd`           | `CLXNativeAd?`                         | 原生广告的素材容器；非原生格式为 `nil`          |
| `adValues`           | `NSDictionary<NSString *, NSString *>` | SDK 为已加载广告提供的元数据；具体值可能因格式或网络而缺失 |

<CodeGroup>
  ```objc Objective-C theme={null}
  - (void)didLoadAd:(CLXAd *)ad {
      NSLog(@"广告格式: %ld", (long)ad.adFormat);
      NSLog(@"网络: %@", ad.networkName);
      NSLog(@"收入: %@", ad.revenue);
  }
  ```

  ```swift Swift theme={null}
  func didLoad(_ ad: CLXAd) {
      print("广告格式: \(ad.adFormat)")
      print("网络: \(ad.networkName ?? "unknown")")
      print("收入: \(ad.revenue ?? 0)")
  }
  ```
</CodeGroup>

### 错误处理

所有 SDK 错误都作为 `CLXError` 对象在代理回调中返回：

| 属性                     | 类型             | 描述      |
| ---------------------- | -------------- | ------- |
| `code`                 | `CLXErrorCode` | 错误类别    |
| `localizedDescription` | `NSString`     | 人类可读的描述 |
| `underlyingError`      | `NSError?`     | 可选的底层错误 |

#### 错误代码类别

| 范围      | 类别   | 常见代码                                                                                                                               |
| ------- | ---- | ---------------------------------------------------------------------------------------------------------------------------------- |
| 0       | 通用   | `CLXErrorCodeInternalError`                                                                                                        |
| 100-199 | 网络   | `CLXErrorCodeNetworkError`、`CLXErrorCodeNetworkTimeout`、`CLXErrorCodeServerError`、`CLXErrorCodeNoConnection`                       |
| 200-299 | 初始化  | `CLXErrorCodeNotInitialized`、`CLXErrorCodeSDKDisabled`、`CLXErrorCodeNoAdaptersFound`、`CLXErrorCodeInvalidAppKey`                   |
| 300-399 | 广告加载 | `CLXErrorCodeNoFill`、`CLXErrorCodeInvalidAdUnit`、`CLXErrorCodeAdsDisabled`                                                         |
| 400-499 | 展示   | `CLXErrorCodeAdNotReady`、`CLXErrorCodeAdAlreadyShowing`                                                                            |
| 600-699 | 适配器  | `CLXErrorCodeAdapterNoFill`、`CLXErrorCodeAdapterTimeout`、`CLXErrorCodeAdapterLoadTimeout`、`CLXErrorCodeAdapterInitializationError` |

## 高级功能

### 调试日志

<CodeGroup>
  ```objc Objective-C theme={null}
  [CloudXCore setMinLogLevel:CLXLogLevelDebug];  // 启用调试日志
  [CloudXCore setMinLogLevel:CLXLogLevelNone];   // 禁用所有日志
  ```

  ```swift Swift theme={null}
  CloudXCore.setMinLogLevel(.debug)  // 启用调试日志
  CloudXCore.setMinLogLevel(.none)   // 禁用所有日志
  ```
</CodeGroup>

**日志级别：** `verbose` \< `debug` \< `info` \< `warn` \< `error` \< `none`

### 展示级别收入追踪

在任何广告格式上设置 `revenueDelegate` 以接收展示级别收入（ILR）回调。`CLXAd` 对象包含以美元计价的收入值和获胜网络名称。

<CodeGroup>
  ```objc Objective-C theme={null}
  self.bannerAd.revenueDelegate = self;

  - (void)didPayRevenueForAd:(CLXAd *)ad {
      NSLog(@"收入: %@ 来自 %@", ad.revenue, ad.networkName);
  }
  ```

  ```swift Swift theme={null}
  bannerAd?.revenueDelegate = self

  func didPayRevenue(for ad: CLXAd) {
      print("收入: \(ad.revenue ?? 0) 来自 \(ad.networkName ?? "unknown")")
  }
  ```
</CodeGroup>

适用于所有广告格式（横幅、MREC、插屏、激励、原生）。

### 代理回调线程

发布方代理回调会在主队列上派发，并且可能相对于触发它们的 SDK 调用以内联方式触发。如果代理方法会再次调用 SDK，请确保处理逻辑可重入。

### 测试模式

测试模式通过设备白名单进行**服务端控制**。这提供了更好的安全性和对哪些设备接收测试广告的控制。

**启用测试模式：**

1. 初始化 SDK 并检查日志中的设备 IFA：
   ```
   [CloudX][INFO] Device IFA for test whitelisting: XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
   ```

2. 复制 IFA 并将其添加到 CloudX 服务器仪表板的设备白名单中

3. SDK 将自动为测试模式配置适配器并在竞价请求中包含测试标志

<Note>
  测试模式由服务器确定，因此您不需要在开发和线上版本之间更改任何代码。
</Note>

### 隐私合规

CloudX SDK 通过从 `NSUserDefaults` 读取标准 IAB 隐私字符串来支持 GDPR 和 CCPA 隐私合规。这些值通常由您的同意管理平台（CMP）自动设置，如 Google UMP、OneTrust 或 Sourcepoint。

#### 工作原理

SDK 自动检测用户位置并读取同意信号：

1. **欧盟用户（GDPR）**：根据 [IAB 全球供应商列表](https://github.com/InteractiveAdvertisingBureau/GDPR-Transparency-and-Consent-Framework) 检查 TCF v2 对目的 1 和 2 的同意和供应商同意（[CloudX 供应商 ID：1510](https://vendor-list.consensu.org/v3/vendor-list.json)）
2. **美国用户（CCPA）**：检查销售/共享选择退出信号
3. **其他地区**：无限制

当用户拒绝同意或选择退出时，SDK 会从广告请求中移除 PII：

* 广告标识符（IDFA）被清除
* 地理坐标（纬度/经度）被移除
* 用户键值不会发送
* 哈希用户 ID 被排除

#### 支持的隐私密钥

| 密钥                     | 标准                                                                                                | 描述                                         |
| ---------------------- | ------------------------------------------------------------------------------------------------- | ------------------------------------------ |
| `IABGPP_HDR_GppString` | [GPP](https://github.com/InteractiveAdvertisingBureau/Global-Privacy-Platform)                    | 全球隐私平台字符串（现代）                              |
| `IABGPP_GppSID`        | GPP                                                                                               | Section IDs（如 "2" 为欧盟，"7" 为美国国家，"8" 为美国加州） |
| `IABTCF_TCString`      | [TCF v2](https://github.com/InteractiveAdvertisingBureau/GDPR-Transparency-and-Consent-Framework) | GDPR 同意字符串（旧版）                             |
| `IABTCF_gdprApplies`   | TCF v2                                                                                            | GDPR 是否适用（1 = 是，0 = 否）                     |
| `IABUSPrivacy_String`  | [US Privacy](https://github.com/InteractiveAdvertisingBureau/USPrivacy)                           | CCPA 隐私字符串（旧版，如 "1YNN"）                    |

<Note>
  当两者都可用时，SDK 优先使用 GPP（现代标准）而非旧版 TCF/US Privacy 字符串。
</Note>

#### 应用追踪透明度（ATT）

在 iOS 14.5+ 上，您必须在 SDK 可以访问 IDFA 之前请求应用追踪透明度授权。在初始化 CloudX SDK 之前请求 ATT 权限：

<CodeGroup>
  ```objc Objective-C theme={null}
  #import <AppTrackingTransparency/AppTrackingTransparency.h>

  if (@available(iOS 14.5, *)) {
      [ATTrackingManager requestTrackingAuthorizationWithCompletionHandler:^(ATTrackingManagerAuthorizationStatus status) {
          // 在 ATT 响应后初始化 CloudX SDK
          [self initializeCloudX];
      }];
  } else {
      [self initializeCloudX];
  }
  ```

  ```swift Swift theme={null}
  import AppTrackingTransparency

  if #available(iOS 14.5, *) {
      ATTrackingManager.requestTrackingAuthorization { status in
          // 在 ATT 响应后初始化 CloudX SDK
          self.initializeCloudX()
      }
  } else {
      initializeCloudX()
  }
  ```
</CodeGroup>

在 Info.plist 中添加 `NSUserTrackingUsageDescription` 键，并说明您需要追踪权限的原因。

#### 手动隐私 API

如果您自行管理用户同意（不使用 CMP），可以直接设置 GDPR 和 CCPA 隐私状态。**请在初始化 SDK 之前调用这些方法** — 部分广告网络 SDK 要求在初始化时设置隐私参数，初始化后设置的值可能不会生效。

<CodeGroup>
  ```objc Objective-C theme={null}
  // 在初始化 SDK 之前设置隐私
  [CloudXCore setHasUserConsent:@YES];
  [CloudXCore setDoNotSell:@NO];

  [[CloudXCore shared] initializeWithConfiguration:config completion:completion];
  ```

  ```swift Swift theme={null}
  // 在初始化 SDK 之前设置隐私
  CloudXCore.setHasUserConsent(true)
  CloudXCore.setDoNotSell(false)

  CloudXCore.shared.initialize(with: config) { sdkConfig, error in
      // ...
  }
  ```
</CodeGroup>

<Note>
  当手动设置值和 CMP 信号同时存在时，CMP 信号（GPP/TCF/US Privacy）优先。手动设置值在未集成 CMP 时作为回退使用。传入 `nil` 可清除手动设置值，完全使用 CMP。
</Note>

### 用户定向

<CodeGroup>
  ```objc Objective-C theme={null}
  // 设置哈希用户 ID 用于定向
  [[CloudXCore shared] setHashedUserID:@"hashed-user-id"];

  // 设置自定义用户键值对（受隐私法规清除）
  [[CloudXCore shared] setUserKeyValue:@"age" value:@"25"];
  [[CloudXCore shared] setUserKeyValue:@"gender" value:@"male"];
  [[CloudXCore shared] setUserKeyValue:@"location" value:@"US"];

  // 设置自定义应用键值对（不受隐私法规影响）
  [[CloudXCore shared] setAppKeyValue:@"app_version" value:@"1.0.0"];
  [[CloudXCore shared] setAppKeyValue:@"user_level" value:@"premium"];

  // 清除所有自定义键值
  [[CloudXCore shared] clearAllKeyValues];
  ```

  ```swift Swift theme={null}
  // 设置哈希用户 ID 用于定向
  CloudXCore.shared.setHashedUserID("hashed-user-id")

  // 设置自定义用户键值对（受隐私法规清除）
  CloudXCore.shared.setUserKeyValue("age", value: "25")
  CloudXCore.shared.setUserKeyValue("gender", value: "male")
  CloudXCore.shared.setUserKeyValue("location", value: "US")

  // 设置自定义应用键值对（不受隐私法规影响）
  CloudXCore.shared.setAppKeyValue("app_version", value: "1.0.0")
  CloudXCore.shared.setAppKeyValue("user_level", value: "premium")

  // 清除所有自定义键值
  CloudXCore.shared.clearAllKeyValues()
  ```
</CodeGroup>

## 技术支持

如需支持，请联系 [mobile@cloudx.io](mailto:mobile@cloudx.io)
