AmpiOS 1.2.1

AmpiOS 1.2.1

测试已测试
语言语言 Obj-CObjective C
许可 MIT
发布上次发布2019年6月

Steve MaskOlha Prokopiuk 维护。



AmpiOS 1.2.1

  • Steve Mask 和 Olha Prokopiuk

Amp-iOS

由 Scaled Inference 提供


Amp.ai 的 iOS 客户端。

Amp.ai

Amp.ai 是一个云端人工智能平台,可以通过做出智能、目标驱动、环境敏感的决定来增强与其集成的任何软件应用。将其视为加强版的 A/B 测试。尽管 A/B 测试可以提供关于所有用户应选择什么信息,但 Amp.ai 将提供针对特定环境并继续根据用户所在环境不断改善,为他们提供最佳决策的决定。

兼容性

iOS 客户端支持与 Swift 4 和 iOS 9 及更高版本兼容的 Objective-C 和 Swift 项目。

入门

参考文档

  1. 从应用商店安装Xcode
  2. Apple开发者
  3. Xcode
  4. Swift
  5. iOS
  6. CocoaPods

CocoaPods

在 Podfile 的目标部分添加 AmpiOS pod

platform :ios, '9.0'
use_frameworks!

target '<Your Target Name>' do
    pod 'AmpiOS'
end

您可以通过指定版本来使用 AmpiOS 的特定版本

pod 'AmpiOS', '~> 1.1'

安装 AmpiOS pod

$ pod install

要将 AmpiOS 升级到最新版本,请运行

$ pod update

安装 pod 后,Xcode 将提示您使用工作区文件重新打开项目。

AmpiOS

初始化

要使用 amp,导入 Amp 框架并使用类创建一个 Amp 实例。Amp 实例应在应用程序启动时创建,以正确处理会话生命周期。以下是在您的 AppDelegate 中初始化 Amp 的示例

Swift

import UIKit
import AmpiOS

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
    ...
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
        amp = Amp(key: "<your_project_key>")
        ...
        return true
    }
}

Objective-C

#import "AppDelegate.h"
@import AmpiOS;

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    _amp = [[Amp alloc] initWithKey:@"<your_project_key>" userId:<userId> config:<Config>];
    ...
    return YES;
}

这些行初始化表示单个会话的amp和session实例,该会话对应于将被提供给您的projectKey。如何定义用户会话完全由您自己决定。请参阅本节以获取详细信息。

上下文

通过向Amp.ai发送事件来观察上下文。在决定点之前发生的会话中的事件形成该决定的“上下文”。随着数据的演变,Amp会自动发现与决策相关的相关上下文,并且会持续这样做。您可以通过显式使用'observe' API调用发送额外的上下文。例如,一个业务特定的上下文可能是一个客户上下文,具有属性“type”,值“Free”或“Premium”。

Swift

amp.observe("Customer", ["type": "Premium"])

Objective-C

[_amp observeWithName:@"Customer" properties:@{@"type": @"Premium"}];

决策

通过调用decide API调用,利用Amp.ai的力量。该调用由呈现给Amp的决定候选者组成。列表中的第一个候选者被Amp视为默认,并且这个决策将用于基线组。Amp会选择导致最大程度提高您业务指标概率的决策。例如,使用Chrome浏览器的日本用户可能会更喜欢购买冰淇淋而不是巧克力。Amp会根据观察到的这个用户群体通常会采取此行动并且提高销售额的这一行为来学习这种行为。

Swift

let colorDecision = amp.decide("Snack", ["choice":["Chocolate", "Ice Cream", "Cookies"]])

Objective-C

NSDictionary* decision = [_amp decideWithName:@"Snack" candidates:@{@"choice": @[@"Chocolate", @"Ice Cream", @"Cookies"]} ttl:nil];

结果

结果就是您正在优化的业务指标。Amp可以同时优化多个指标。在定义了指标后,Amp.ai通过一个observe调用得知结果。

Swift

amp.observe("Sale", [])

Objective-C

[_amp observeWithName:@"Sale" properties:@{}];

高级设置

加载规则

当您需要确保通过 decide() 做出的决策是基于服务器提供的规则时使用此功能。一个常见的用例是在应用程序启动时必须做出一次性的决策。如果规则已经可用,则回调将立即通过此方法调用。如果规则尚未准备好,它将等待同步完成并执行回调。

Swift

dialog.show()
amp.loadRules(timeout: timeoutInMilliseconds) { error in
        // The callback is executed on the main thread, so it's safe to change the UI
        dialog.dismiss()

        // Chose a color for button that will suite current customer
        let colorDecision = amp.decide(name: "ButtonColor", candidates: ["color":["blue", "orange", "green"]])
        ...
}

Objective-C

[dialog show];
[amp loadRulesWithTimeout:timeoutInMilliseconds callback:^(NSError *error) {
        // The callback is executed on the main thread, so it's safe to change the UI
        [dialog dismiss];

        // Chose a color for button that will suite current customer
        NSDictionary* colorDecision = [amp decideWithName:"ButtonColor" candidates: @{@"color":@[@"blue", @"orange", @"green"]}];
        ...
}];

会话

默认情况下,会话在非活动时间段(应用程序处于后台状态并且没有触发事件)超过 sessionTTL,或者自会话创建以来的时间间隔超过 sessionLifetime 时结束。sessionTTLsessionLifetime 可以在 AMP 初始化期间设置。您还可以使用以下方法显式结束当前会话并启动一个新的会话。

Swift

amp.startNewSession()

Objective-C

[amp.startNewSession startNewSession];

内置事件

默认情况下,使用 AmpiOS 客户端时,我们将通过 AmpTap 事件在按钮上观察点击,并在 AmpSession 事件上获取一般会话信息。

配置选项

以下选项可用。

名称 默认值 数据类型 详细信息
logLevel .warn LogLevel .error, .warn, .info, .debug
builtinEvents [String] 数组 初始化时创建的事件
sessionTTL 15分钟 Int64 会话在毫秒中的存活时间
sessionLifetime 24小时 Int64 毫秒中的会话生存时间

预览模式

当需要进行决策调用变体的测试时,预览模式可以帮助您做到这一点。启用后,将允许预先选择下一个决策调用的结果。注意:不要在发布版本中使用它,因为它仅用于测试。

要启用预览模式,请在与Amp相关的配置中启用它。

Swift

let config = ConfigBuilder()
            .set(previewMode: true)
            .build()
let amp = Amp(key: key, config: config)

Objective-C

Config *config = [[[[ConfigBuilder alloc] init]
                       setWithPreviewMode:@YES] build];
Amp *amp = [[Amp alloc] initWithKey:key userId:nil config:config];

它将看起来像这样:预览模式

使用

您可以使用Amp的许多方法。您可能希望跟踪您的应用中每个页面通常被访问的频率或者用户在可滚动页面中滚动到的位置。如果您的应用需要注册和登录,您可能希望跟踪注册按钮的点击次数,因为这可能帮助您提高用户的注册率。可能性无限,而且使用Amp,它不仅将跟踪您要求它跟踪的所有内容,它还将检查这些事件发生的上下文。有了这些信息,Amp将做出最佳决定来提高您的业务目标。以下是如何在您的应用中发出observedecide请求的几个示例。

观察使用

我想跟踪访问的页面

这是iOS生命周期方法中使用的一种方法,即viewDidLoad

Swift

override func viewDidLoad() {
    super.viewDidLoad()

    if let title = self.navigationItem.title {
        amp?.observe(name: "AmpPage", properties: ["title": title])
    }
}

Objective-C

- (void)viewDidLoad {
    [super viewDidLoad];
    
    NSString* title = [[self navigationItem] title];
    if (title) {
        [_amp observeWithName:@"AmpPage" properties:@{@"title": title}];
    }
}

我想跟踪按钮点击

Amp已经通过我们的内置事件之一AmpTap为您跟踪这些。您只需使用这些,或者您也可以通过动作方法创建自定义的。

Swift

@IBAction func buttonPressed(_ sender: UIButton) {
    amp?.observe(name: "Signup", properties: [:])
}

Objective-C

- (IBAction)buttonPressed:(UIButton *)sender {
    [_amp observeWithName:@"Signup" properties:@{}];
}

我想追踪人们正在搜索什么

在这里使用代理方法来帮您。

Swift

// MARK: - UISearchBarDelegate methods

func searchBarTextDidEndEditing(_ searchBar: UISearchBar) {
    if let textValue = searchBar.text {
        amp?.observe(name: "Search", properties: ["value": textValue])
    }
}

Objective-C

-(void)searchBarTextDidEndEditing:(UISearchBar *)searchBar {
    NSString* textValue = [searchBar text];
    if (textValue) {
        [_amp observeWithName:@"Search" properties:@{@"value": textValue}];
    }
}

我想追踪我的用户在页面上滚动的程度

以下示例仅使用 UITableViewDelegate 在滚动大于100时进行观察。

Swift

// MARK: - UITableViewDelegate methods

func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {
    if targetContentOffset.pointee.y > 100 {
        amp?.observe(name: "PageScroll", properties: ["page":"Welcome"])
    }
}

Objective-C

- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset {

    if (targetContentOffset->y > 100) {
        [_amp observeWithName:@"AmpScrollDrag" properties:@{}];
    }
}

决定用途

我想更新视图中控件的外观

Swift

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)

    let decision = amp.decide(name: "ButtonStyle", candidates: ["color": ["orange", "blue", "green"]])
    
    let colors = ["orange": UIColor.orange, "blue": UIColor.blue, "green": UIColor.green]
    pressMeBtn.setTitleColor(colors[decision["color"] as! String], for: .normal)
}

Objective-C

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    
    NSDictionary* decision = [_amp decideWithName:@"ButtonStyle" candidates:@{@"color": @[@"orange", @"blue", @"green"]} ttl:nil];
    
    NSDictionary* colors = @{@"orange": [UIColor orangeColor], @"blue": [UIColor blueColor], @"green": [UIColor greenColor]};
    
    [_pressMeBtn setTitleColor:[colors objectForKey:[decision objectForKey:@"color"]] forState:UIControlStateNormal];
}

我想确定要执行哪个segue

您可能想确定创建新的功能向导是否真的有用,或者用户是否只是在跳过它。也许您正在尝试决定一系列页面的流程。无论您的使用案例如何,您都可以应用决策来确定下一个导航到的viewController。以下是一个简单的示例,说明在方向改变时如何决定使用哪个segue。

Swift

NotificationCenter.default.addObserver(self, selector: #selector(ViewController.orientationChanged), name: NSNotification.Name.UIApplicationDidChangeStatusBarOrientation, object: nil)
...
@objc func orientationChanged(notification: Notification) {
    let deviceOrientation = UIDevice.current.orientation
    let decision = amp.decide("LandscapeView", ["view": ["SplitLeft", "Normal", "SplitRight"]])

    if UIDeviceOrientationIsLandscape(deviceOrientation) {
        self.performSegue(withIdentifier: "decision["view"] as! String, sender: self)
    }
}

Objective-C

[NSNotificationCenter.defaultCenter addObserver:self selector:@selector(orientationChanged:) name:@"UIApplicationDidChangeStatusBarOrientationNotification" object:NULL];
...
- (void)orientationChanged:(NSNotification *) sender {                        }
    UIDeviceOrientation deviceOrientation = [UIDevice currentDevice].orientation;
    NSDictionary* decision = [_amp decideWithName:@"LandscapeView" candidates:@{@"view": @[@"SplitLeft", @"Normal", @"SplitRight"]} ttl:nil];
    
    if (UIDeviceOrientationIsLandscape(deviceOrientation)) {
        [self performSegueWithIdentifier:[NSString stringWithFormat:@"%@", [decision objectForKey:@"view"]] sender:self];
    }
}