App iOS全栈API开发指南(swift语言)

本文详细介绍IOS swift语言如何在云眼平台进行AB测试。

设计优化方案

下面我们以一个简单的swift APP为例。其中包含一段文本和一个按钮,现在我们提出假设:文本的内容会影响用户的点击率。所以我们要进行AB测试的就是APP中文本的内容,衡量结果的唯一主目标就是按钮的点击率。

配置优化方案

在设计完优化方案之后我们需要在云眼平台对优化方案进行创建和配置。

创建优化方案

在云眼控制台中点击“业务优化”,等到页面加载完成后点击“创建优化方案”按钮,平台选择“全栈API”,填写优化方案名称,然后点击“确认”创建优化方案。创建完成后点击对应优化方案的“编辑”按钮来打开编辑器。

配置优化方案

在“版本设置”中根据优化方案设计的情况来添加版本并分配流量,通常情况下均分流量即可。总流量根据实际流量调整,业务流量较大的应用选择部分流量参与测试就足够了。

 

 

 

 

 

 

 

根据优化方案设计的情况,将需要用到的衡量指标创建为一个目标。点击“+”号将其添加到优化方案当中。

 

 

 

 

 

设置受众可以将优化方案定位到在云眼控制台预先定义的特定受众群体中,云眼将会在激活优化方案时通过属性值评估用户是否满足受众条件,从而决定是否激活优化方案。在云眼控制台中点击“业务优化”,业务优化界面打开后再点击“自定义属性(全栈)”。点击创建自定义属性,输入自定义属性的名称和描述,点击确定按钮。

在编辑器中点击“创建受众”,输入受众的名称和描述,将右侧已创建好的自定义属性拖拽至受众条件下,点击“保存受众”按钮。

启动优化方案,完成配置工作。

安装SDK

打开云眼控制台,然后点击“业务优化”,业务优化界面打开后点击“SDK下载与安装”

在新打开的页面中,选择”IOS SDK安装“,再从下方选择“全栈API SDK安装”,根据下方提示完成SDK安装。

在添加完云眼SDK之后,在项目中右键新建一个桥接文件Header File,为该文件命名然后点击create。

创建好桥接文件后,在项目中选择Build Settings,然后找到Swift Compiler – General下的Objective-C Bridging Header,点击该选项,当右侧出现弹框时将刚创建的桥接文件拖入其中。

然后在桥接文件#endif前引入云眼SDK

#import "EyeofcloudSDKiOS/EyeofcloudSDKiOS.h"

SDK初始化

所有和AB测试相关的接口都是定义在EOCClient这个类上的,通过这个类才能够版本抽签、触发目标、获取参数从而进行AB测试。同时,SDK还提供了一个EOCManager类来负责EOCClient的构造和获取、配置文件(包含AB测试信息)的下载和更新、配置文件的缓存管理等等。所以,初始化SDK的第一步就是构造一个EOCManager。建议在Appdelegate上设置一个私有属性保存全局唯一的一个EOCManager,再设计一个getEOCManager的接口将其暴露出来。

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.

//---- Create eoc Manager ----
   eocManager = EOCManager.init{ (build : EOCManagerBuilder?) in
      build?.projectId = "PROJECT_ID"
   }
   return true
}
func getEOCManager() -> EOCManager? {
        return eocManager
    }

其中参数PROJECT_ID可以从“SDK下载与安装”界面中查到。

如果您正在使用私有部署的云眼系统,则需要修改配置文件和事件发送的URL。 首先,实例化EOCDatafileManagerDefault类和EOCEventDispatcherDefault类,在各自的初始化方法里设置相应的URL。然后,调用EOCManager的初始化方法,并将以上两个类的实例作为参数传入并赋值给build 。

// ---- Create the Event Dispatcher ----
    let eventDispatcher = EOCEventDispatcherDefault.init{ (build : EOCEventDispatcherBuilder?) in
      build?.eventDispatcherEventURL = "事件发送URL"
}
// ---- Create the Datafile Manager ----
    let datafileManager = EOCDatafileManagerDefault.init{ (build: EOCDatafileManagerBuilder?) in
      build!.projectId = "PROJECT_ID"
      build!.networkServiceCDNServerURL = "配置文件URL"
}
//---- Create eoc Manager ----
    let eocManager = EOCManager.init{ (build : EOCManagerBuilder?) in
      build?.projectId = "PROJECT_ID"
      build?.datafileManager = datafileManager!
      build?.eventDispatcher = eventDispatcher
}

在构造完EOCManager对象后,我们需要调用EOCManager的initialize方法完成EOCClient的初始化。该方法会下载配置文件,然后根据配置文件构造一个EOCClient对象并将其保存在eocManager中。在之后需要使用SDK的地方,通过EOCManager的getEyeofcloud方法获取缓存的EOCClient对象再来调用相关接口。

let eocClient = eocManager?.initialize()

这里需要注意的一点是,在网络不通的情况下,EOCClient初始化就会失败。例如,首次启动APP时,会触发一个弹框,要求用户设定APP的网络权限。在完成设定之前,APP的网络请求是被禁止的,从而导致EOCClient初始化失败。为了保证AB测试的顺利进行,就要把EOCClient的初始化推迟到APP联网之后。一个简单的办法就是使用AFN监听APP的网络状态,一旦APP联网就开始初始化EOCClient以及加载其它资源,然后重新渲染APP的界面。

在调用SDK的接口时,会需要一个唯一的userId来标识用户。另外,如果要使用受众功能,还会需要用户的属性值。为了方便,可以在Appdelegate中定义两个方法getUserAttributes 和getUserId。

 func getUserId() -> String? {
        userId = String(Int(arc4random_uniform(300000)))
        return userId
    }
    
 func getUserAttributes() -> [String : String]? {
        userAttributes = [
            "Gender": "female"
        ]
        return userAttributes
    }

非参数化AB测试方案

非参数化方法使用SDK的版本抽签接口得到一个版本名称,依据版本名称编写if-else的分支代码,不同版本执行不同的代码从而产生版本差异。该方案灵活性较差,每次进行新的测试都需要更新应用程序,只有在参数化方案无法满足需求时才推荐使用。

对于非参数化方案,给出两种常见的使用方式来产生多个版本。

第一种方式是在打开新的View前,进行版本抽签,依据抽签结果创建不同的View从而形成不同的版本。这种方式比较适合版本差异较大的情况,直接制作多个View作为不同的版本。

  func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        // Override point for customization after application launch.
        
        //---- Create eoc Manager ----
                eocManager = EOCManager.init{ (build : EOCManagerBuilder?) in
                    build?.projectId = "PROJECT_ID"
                }
        //---- initialization ----
                let eocClient = eocManager?.initialize()
                let variation = eocClient?.activate(ExperimentName,userId: self.userId)
                self.setRootViewController(eocClient: eocClient, bucketedVariation:variation)
              return true
    }
    
    func setRootViewController(eocClient: EOCClient!, bucketedVariation:EOCVariation?) {
        DispatchQueue.main.async {
            var storyboard : UIStoryboard
            storyboard = UIStoryboard(name: "Main", bundle: nil)
            var rootViewController = storyboard.instantiateViewController(withIdentifier: "DefaultViewController")
            if (bucketedVariation?.variationKey=="优化版本#1") {
                // load variation page
                rootViewController = storyboard.instantiateViewController(withIdentifier: "EOCOPTViewController")
            }else{
                rootViewController = storyboard.instantiateViewController(withIdentifier: "EOCORIViewController")
            }
            
            if let window = self.window {
                window.rootViewController = rootViewController
            }
        }
    }

第二种方式是在需要体现版本差异的地方进行版本抽签,依据抽签结果进入不同的代码逻辑,从而使得应用的界面或者行为变得不同。例如,通过代码修改界面的样式

override func viewDidLoad() {
        super.viewDidLoad()
        self.eocClient = appDelegate.getEOCManager()?.getEyeofcloud()
        let variation =  self.eocClient?.activate(ExperimentName, userId: appDelegate.getUserId()!, attributes: appDelegate.getUserAttributes())
        if variation?.variationKey == "优化版本#1" {
            ori.text = "这是版本A界面的优化版本"
        }else{
            ori.text = "这是版本A界面"
        }
    }

完成版本差异化的代码之后,添加触发目标的代码。

 @IBAction func click(_ sender: Any) { 
  self.eocClient?.track(GoalName, userId: appDelegate.getUserId()!, attributes: appDelegate.getUserAttributes())
}

参数化AB测试方案

参数化方案希望的是将应用程序中的一些关键变量动态化,使其不再写死在程序中,而是从一个可变的配置文件中读取对应的值。例如,可以参数化示例中的文本内容,通过修改配置文件的内容达到修改应用程序行为的目的。

选择参数和目标

在将应用程序参数化前,需要考虑哪些变量是需要参数化的以及哪些目标是有可能使用到的。所有将来可能进行AB测试的关键地方,都建议将其参数化,比如关键按钮(注册、购买等)的一些属性、控制应用行为的一些关键参数、甚至是推荐算法的一些参数等。这样,当将来要进行AB测试的时候就不再需要发布新本应用了。目标的选择往往是和业务指标相关的一些行为,比如一些按钮的点击,把可能用来衡量结果的目标都考虑进去。在本例中我们选择的参数化元素为界面中的文本内容,目标为界面中的按钮点击率。

配置参数化优化方案

在选择完需要参数化的变量和目标后,要在编辑器中创建这些选出的变量和目标。目标的创建和上面介绍的一样。下面介绍变量的创建,在设置变量处,点击“创建变量”。

在弹出的界面中填写变量名称,选择变量类型和默认值,点击“保存”完成创建。

在创建完变量和目标之后,就要修改我们的应用程序了。首先是变量的改动,可以通过调用variableString、variationDouble、variationInteger、variationBoolean这四个方法去获取变量,然后在程序中使用这些得到的变量。

NSString *accoutPlaceHolder = [self.eocClient variableString:@"LoginAccountPlaceHolder" userId:self.userId attributes:self.userAttributes activateExperiment:true];
   @IBAction func click(_ sender: Any) {
        self.eocClient?.track("click", userId: appDelegate.getUserId()!)
    }
    override func viewDidLoad() {
        super.viewDidLoad()
        self.eocClient = appDelegate.getEOCManager()?.getEyeofcloud()
        let content = self.eocClient?.variableString("text-content",userId:appDelegate.getUserId()!,activateExperiment: true)
        ori.text = content
    }

完成应用程序的参数化并添加触发目标的代码之后,随时都可以在云眼控制台创建优化方案进行AB测试,而这个过程是不需要更新应用程序的。在假设的基础上设计实验后,可以在编辑器的“设置变量”中添加需要使用的变量,并为各个版本填写相应的值,从而产生不同的版本。之后再添加需要的目标并保存就可以完成实验的配置,最后启动实验。

查看实验结果

当实验运行一段时间后,就可以到云眼控制台查看实验的运行结果。

Demo代码

下载demo代码(包含文中对应的三种方式)

iOSFullStackActivateDifferentView:非参数化第一种方案
iOSFullStackActivateNormal:非参数化第二种方案
iOSFullStackParameter:参数化方案

免费试用,转化率提升就是这样简单快速 立即试用