# 演练模式

> 来源：https://help.gravity-engine.com/docs/client-sdk/ios/advanced/dry-run-mode
> 说明 iOS SDK 如何通过 dryRunEventWithCallback 接入引力演练模式，包含 trace_id 获取、回调处理与付费/关键行为向媒体回传的示例代码。



> **注意**
> 此文档主要说明引力 iOS SDK 演练模式相关的代码接入部分。运营和投放的后台配置请参考[引力 & 回传演练模式](https://gravityengine.feishu.cn/wiki/G6lwwJn8NiDr9wkYUZFcp5wonme?fromScene=spaceOverview)。
>
> 目前 iOS 支持演练的媒体平台如下：
>
> * iOS：仅腾讯（主要是预归因的全埋点上报的情况）

为了该模式更灵活的使用，建议将演练模式在代码中配置为一个开关，方便联调和测试。

## 接入事项 [#接入事项]

因演练模式主要是为了付费的自定义回传，为了减少投放每次调整映射策略，导致的客户端频繁改动，引力提供了演练模式，支持客户端技术从引力获取具体订单对应的回传结果，再执行给媒体的回传。

请客户端技术务必确认下面的流程图步骤明确后开始接入。

### iOS SDK 演练 [#ios-sdk-演练]

以下是 iOS SDK，技术需要处理的 5 大步骤：

1. 升级引力 SDK 到 [5.0.14](https://github.com/GravityInfinite/GravityEngine-iOS-Demo/releases) 及以上版本，建议使用最新版本；
2. 正常按照[引力接入文档](/docs/client-sdk/ios/quickstart)接入；
3. 在用户发生付费行为时，客户端需要获取到 `trace_id`，获取方式：
   1. **如果历史是通过客户端上报付费事件给引力**：调用引力 SDK 付费事件上报接口 `trackPayEvent`，该接口会返回一个 `trace_id`，请使用变量保存好；
   2. **如果历史是通过服务端 API 上报付费事件给引力**：API 上报之后，您的服务端需要返回本次事件上报的 `$order_id` 给您的客户端，此时 `$order_id` 即为 `trace_id`
4. 然后调用 `dryRunEventWithCallback` 接口，传入上一步获取的 `trace_id`；
5. 客户在 `dryRunEventWithCallback` 方法的回调函数中获取当前事件所映射的媒体回传事件，并根据返回的信息来执行向媒体 SDK 上报事件的逻辑；

核心代码实现逻辑如下，请注意看注释！（包含了关键行为和付费相关代码，根据实际取用）

```objective-c
@interface ViewController ()<GravityDryRunEventDelegate>

-(void)onFailed:(NSString *)errorMsg{
    NSLog(@"dryRunEvent:onFailed:%@",errorMsg);
}
-(void)onEmpty:(GEDryRunEventEmptyType)emptyType{
    switch (emptyType) {
        case GEDryRunEventEmptyTypeNotEnable:
            NSLog(@"dryRunEvent:onEmpty:NotEnable");
            break;
        case GEDryRunEventEmptyTypeNoInPostbackWindow:
            NSLog(@"dryRunEvent:onEmpty:NoInPostbackWindow");
            break;
        case GEDryRunEventEmptyTypeSkip:
            NSLog(@"dryRunEvent:onEmpty:Skip");
            break;
        default:
            break;
    }
}
-(void)onTrackPay:(NSString *)mediaType payAmount:(int)amount traceId:(NSString*)traceId otherParams:(NSDictionary*)otherParams{
    NSLog(@"dryRunEvent:onTrackPay:%@:%@:%@",mediaType,traceId,@(amount));
}
-(void)onTrackKeyActive:(NSString *)mediaType traceId:(NSString*)traceId otherParams:(NSDictionary*)otherParams{
    NSLog(@"dryRunEvent:onTrackKeyActive:%@:%@",mediaType,traceId);
}

//调用示例
NSString * traceId = [instance trackPayEventWithAmount:300 withPayType:@"CNY" withOrderId:[NSString stringWithFormat:@"order_id_%@",@([[NSDate date] timeIntervalSince1970])] withPayReason:@"月卡" withPayMethod:@"支付宝"];
[instance dryRunEventWithCallback:traceId otherParams:@{} callback:self];
```

上述示例中 `instance` 为已初始化的引力 iOS SDK 实例，请确保其已完成 `setupAndStart` 初始化后再调用演练模式接口。

`onTrackPay` 回调中的 `payAmount` 参数单位是分，给具体媒体回传的时候，请留意是否需要转化成元\~

## 常见问题 [#常见问题]

1. **如果代码执行了演练模式的部分，但是应用没有配置，演练模式是否生效？**

   1. 不开启演练模式，调用演练模式的接口会返回 `onEmpty`（当前用户归因媒体未开启演练模式）；
   2. 需同时开启，否则演练模式不生效。

2. **是否有相关接口能获取到应用管理的演练模式是否开启以及选择的类型？**

   1. 暂时无法获取。

3. **如何验证演练模式接入是否成功？**

   1. 在引力后台开启演练模式，调用演练模式之后验证返回的数据是否符合配置的映射。

4. **当前用户归因媒体未开启演练模式怎么理解？**

   1. 当用户来自**暂不支持演练的渠道或未开启演练模式**时会显示此提示。目前 iOS 端仅**腾讯**的归因用户可开启演练，其他渠道及自然量用户均会返回此状态。

5. **订单细查 SDK 回传状态分别是什么含义？**

   1. 等待判断：条件映射状态为未通过的；
   2. 无需 SDK 回传：满足 SDK 映射的条件及回传比例，执行扣传；
   3. SDK 待回传：等待 SDK 返回回传结果，一般是没有调用演练模式接口；
   4. SDK 已回传：已通过 SDK 回传。
