• 개발자 가이드
  • SDK Integration
  • iOS SDK

SDK 마이그레이션 가이드 - iOS SDK

에어브릿지 iOS SDK를 업데이트하는 과정에 필요한 내용을 확인할 수 있습니다. 현재 버전 이후부터 업데이트 이후 버전까지의 내용을 모두 확인하는 것을 권장합니다.

v1.x에서 v4.0으로 업데이트

에어브릿지 iOS SDK를 v4.0으로 업데이트하면 확인해 주세요.

iOS SDK 이름이 AirBridge에서 Airbridge로 변경되었습니다. AirBridge 클래스가 Airbridge 클래스로 변경되었습니다. 함수와 옵션의 이름이 변경되었습니다.

옵션

함수

클래스

상수

SDK 설치 및 초기화

CocoaPods 패키지명, SwiftPackageManager Git 주소, 직접 설치 다운로드 URL 등이 변경되었습니다. 기존 iOS SDK를 삭제한 후에 에어브릿지 가이드에 따라 다시 설치해 주세요.

SDK 초기화에 사용하는 AirBridge.getInstance 함수가 Airbridge.initializeSDK 함수로 변경되었습니다. 또한 옵션 설정 함수가 AirbridgeOption, AirbridgeOptionBuilder 클래스들로 변경되었습니다. SDK의 옵션은 더는 런타임에 변경되지 않습니다.

아래 맵핑을 참고해 새로운 SDK 초기화 코드를 작성해 주세요.

1234567
import Airbridge
...
let option = AirbridgeOptionBuilder(name: "YOUR_APP_NAME", token: "YOUR_APP_SDK_TOKEN")
    .setLogLevel(.warning)
    .setSessionTimeout(second: 300)
    .build()
Airbridge.initializeSDK(option: option)
12345678
#import <Airbridge/Airbridge.h>
...
AirbridgeOptionBuilder* optionBuilder = [[AirbridgeOptionBuilder alloc] initWithName:@"YOUR_APP_NAME"
                                                                               token:@"YOUR_APP_SDK_TOKEN"];
[optionBuilder setLogLevel:AirbridgeLogLevelWarning];
[optionBuilder setSessionTimeoutWithSecond:300];
AirbridgeOption* option = [optionBuilder build];
[Airbridge initializeSDKWithOption:option];

1234567
import Airbridge
...
let option = AirbridgeOptionBuilder(name: "YOUR_APP_NAME", token: "YOUR_APP_SDK_TOKEN")
    .setLogLevel(.warning)
    .setSessionTimeout(second: 300)
    .build()
Airbridge.initializeSDK(option: option)
12345678
#import <Airbridge/Airbridge.h>
...
AirbridgeOptionBuilder* optionBuilder = [[AirbridgeOptionBuilder alloc] initWithName:@"YOUR_APP_NAME"
                                                                               token:@"YOUR_APP_SDK_TOKEN"];
[optionBuilder setLogLevel:AirbridgeLogLevelWarning];
[optionBuilder setSessionTimeoutWithSecond:300];
AirbridgeOption* option = [optionBuilder build];
[Airbridge initializeSDKWithOption:option];

딥링크

AirBridge.setDeeplinkCallback 함수가 Airbridge.handleDeeplink 함수와 handleDeferredDeeplink 함수로 대체되었습니다.

기존 AirBridge.setDeeplinkCallback 함수를 에어브릿지 대시보드에 등록한 스킴딥링크를 처리하는 함수와 다른 딥링크를 처리하는 함수로 분리해 구현해야 합니다. 아래 DeeplinkHandler 클래스를 참고해 주세요.

123456789101112131415161718192021
import Foundation

final class DeeplinkHandler {
    private init() {}

    static func handleSchemeDeeplink(url: URL) -> Bool {
        if url.scheme != "YOUR_SCHEME" {
            return false
        }

        // REQUIRE: show content

        return true
    }

    static func handleOtherDeeplink(url: URL) -> Bool {
        // OPTION: show content

        return true
    }
}
1234567891011121314151617181920212223242526272829303132
#import <Foundation/Foundation.h>

@implementation ABDeeplinkHandler

- (instancetype) init __unavailable;

+ (BOOL)handleSchemeDeeplink:(NSURL *)url;
+ (BOOL)handleOtherDeeplink:(NSURL *)url;

@end
...
#import "ABDeeplinkHandler.h"

@interface ABDeeplinkHandler : NSObject

+ (BOOL)handleSchemeDeeplink:(NSURL *)url {
    if (![url.scheme isEqualToString:@"YOUR_SCHEME"]) {
        return NO;
    }

    // REQUIRE: show content

    return YES;
}

+ (BOOL)handleOtherDeeplink:(NSURL *)url {
    // OPTION: show content

    return YES;
}

@end

AirBridge.deeplink().handle (또는 handleUniversalLink)와 AirBridge.deeplink().handleURLSchemeDeeplinkAirbridge.trackDeeplink로 대체되었습니다.

1. 시스템 방식에 따라 AirBridge.deeplink().handle (또는 handleUniversalLink)와 AirBridge.deeplink().handleURLSchemeDeeplink 함수를 호출하는 부분을 삭제합니다.

2. Airbridge.trackDeeplink 함수와 Airbridge.handleDeeplink 함수를 호출합니다.

Airbridge.handleDeeplink 함수는 에어브릿지 딥링크가 입력되면 true와 함께 스킴 딥링크를 콜백으로 제공합니다. 에어브릿지 딥링크가 아니면 false와 함께 콜백을 제공하지 않습니다.

3. onSuccess 콜백에서 에어브릿지로 실행된 스킴 딥링크를 처리하는 함수를 호출합니다.

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
import UIKit
import Airbridge

class SceneDelegate: UIResponder, UIWindowSceneDelegate {
    var window: UIWindow?

    // when terminated app is opened with scheme deeplink or universal links
    func scene(
        _ scene: UIScene,
        willConnectTo session: UISceneSession,
        options connectionOptions: UIScene.ConnectionOptions
    ) {
        // when app is opened with scheme deeplink
        if let url = connectionOptions.urlContexts.first?.url {
            // track deeplink
            Airbridge.trackDeeplink(url: url)

            // handle airbridge deeplink
            var isHandled = Airbridge.handleDeeplink(url: url) { url in
                DeeplinkHandler.handleSchemeDeeplink(url: url)
            }
            if isHandled { return }

            // handle scheme deeplink
            isHandled = DeeplinkHandler.handleSchemeDeeplink(url: url)
            if isHandled { return }

            // handle other deeplink
            isHandled = DeeplinkHandler.handleOtherDeeplink(url: url)
        }
        // when app is opened with universal links
        else if let userActivity = connectionOptions.userActivities.first {
            // track deeplink
            Airbridge.trackDeeplink(userActivity: userActivity)

            // handle airbridge deeplink
            var isHandled = Airbridge.handleDeeplink(userActivity: userActivity) { url in
                DeeplinkHandler.handleSchemeDeeplink(url: url)
            }
            if isHandled { return }

            // handle other deeplink
            if let url = userActivity.webpageURL {
                isHandled = DeeplinkHandler.handleOtherDeeplink(url: url)
            }
        }
    }

    // when backgrounded app is opened with scheme deeplink
    func scene(
        _ scene: UIScene,
        openURLContexts URLContexts: Set<UIOpenURLContext>
    ) {
        guard let url = URLContexts.first?.url else { return }

        // track deeplink
        Airbridge.trackDeeplink(url: url)

        // handle airbridge deeplink
        var isHandled = Airbridge.handleDeeplink(url: url) { url in
            DeeplinkHandler.handleSchemeDeeplink(url: url)
        }
        if isHandled { return }

        // handle scheme deeplink
        isHandled = DeeplinkHandler.handleSchemeDeeplink(url: url)
        if isHandled { return }

        // handle other deeplink
        isHandled = DeeplinkHandler.handleOtherDeeplink(url: url)
    }

    // when backgrounded app is opened with universal links
    func scene(
        _ scene: UIScene,
        continue userActivity: NSUserActivity
    ) {
        // track deeplink
        Airbridge.trackDeeplink(userActivity: userActivity)

        // handle airbridge deeplink
        var isHandled = Airbridge.handleDeeplink(userActivity: userActivity) { url in
            DeeplinkHandler.handleSchemeDeeplink(url: url)
        }
        if isHandled { return }

        // handle other deeplink
        if let url = userActivity.webpageURL {
            isHandled = DeeplinkHandler.handleOtherDeeplink(url: url)
        }
    }
}
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
#import "SceneDelegate.h"
#import "ABDeeplinkHandler.h"
#import <Airbridge/Airbridge.h>

@interface SceneDelegate ()

@end

@implementation SceneDelegate

// when terminated app is opened with scheme deeplink or universal links
- (void)scene:(UIScene *)scene willConnectToSession:(UISceneSession *)session options:(UISceneConnectionOptions *)connectionOptions {
    // when app is opened with scheme deeplink
    NSURL* url = connectionOptions.URLContexts.allObjects.firstObject.URL;
    NSUserActivity* userActivity = connectionOptions.userActivities.allObjects.firstObject;
    if (url != nil) {
        // track deeplink
        [Airbridge trackDeeplinkWithUrl:url];

        // handle airbridge deeplink
        BOOL isHandled = [Airbridge handleDeeplinkWithUrl:url onSuccess:^(NSURL* url) {
            [ABDeeplinkHandler handleSchemeDeeplink:url];
        }];
        if (isHandled) { return; }

        // handle scheme deeplink
        isHandled = [ABDeeplinkHandler handleSchemeDeeplink:url];
        if (isHandled) { return; }

        // handle other deeplink
        isHandled = [ABDeeplinkHandler handleSchemeDeeplink:url];
    }
    else if (userActivity != nil) {
        // track deeplink
        [Airbridge trackDeeplinkWithUserActivity:userActivity];

        // handle airbridge deeplink
        BOOL isHandled = [Airbridge handleDeeplinkWithUserActivity:userActivity onSuccess:^(NSURL* url) {
            [ABDeeplinkHandler handleSchemeDeeplink:url];
        }];
        if (isHandled) { return; }

        // handle other deeplink
        NSURL* url = userActivity.webpageURL;
        if (url != nil) {
            isHandled = [ABDeeplinkHandler handleOtherDeeplink:url];
        }
    }
}

// when backgrounded app is opened with scheme deeplink
- (void)scene:(UIScene *)scene openURLContexts:(NSSet<UIOpenURLContext *> *)URLContexts {
    NSURL* url = URLContexts.allObjects.firstObject.URL;
    if (url == nil) { return; }

    // track deeplink
    [Airbridge trackDeeplinkWithUrl:url];

    // handle airbridge deeplink
    BOOL isHandled = [Airbridge handleDeeplinkWithUrl:url onSuccess:^(NSURL* url) {
        [ABDeeplinkHandler handleSchemeDeeplink:url];
    }];
    if (isHandled) { return; }

    // handle scheme deeplink
    isHandled = [ABDeeplinkHandler handleSchemeDeeplink:url];
    if (isHandled) { return; }

    // handle other deeplink
    isHandled = [ABDeeplinkHandler handleSchemeDeeplink:url];
}

// when backgrounded app is opened with universal links
- (void)scene:(UIScene *)scene continueUserActivity:(NSUserActivity *)userActivity {
    // track deeplink
    [Airbridge trackDeeplinkWithUserActivity:userActivity];

    // handle airbridge deeplink
    BOOL isHandled = [Airbridge handleDeeplinkWithUserActivity:userActivity onSuccess:^(NSURL* url) {
        [ABDeeplinkHandler handleSchemeDeeplink:url];
    }];
    if (isHandled) { return; }

    // handle other deeplink
    NSURL* url = userActivity.webpageURL;
    if (url != nil) {
        isHandled = [ABDeeplinkHandler handleOtherDeeplink:url];
    }
}

@end
1234567891011121314151617181920212223242526272829
import SwiftUI
import Airbridge

@main
struct ActualApp: App {
    var body: some Scene {
        WindowGroup {
            ContentView()
                // when app is opened with scheme deeplink or universal links
                .onOpenURL { url in
                    // track deeplink
                    Airbridge.trackDeeplink(url: url)

                    // handle airbridge deeplink
                    var isHandled = Airbridge.handleDeeplink(url: url) { url in
                        DeeplinkHandler.handleSchemeDeeplink(url: url)
                    }
                    if isHandled { return }

                    // handle scheme deeplink
                    isHandled = DeeplinkHandler.handleSchemeDeeplink(url: url)
                    if isHandled { return }

                    // handle other deeplink
                    isHandled = DeeplinkHandler.handleOtherDeeplink(url: url)
                }
        }
    }
}
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455
import UIKit
import Airbridge

@main
class AppDelegate: UIResponder, UIApplicationDelegate {   
    var window: UIWindow?

    // when app is opened with scheme deeplink
    func application(
        _ app: UIApplication,
        open url: URL,
        options: [UIApplication.OpenURLOptionsKey : Any] = [:]
    ) -> Bool {
        // track deeplink
        Airbridge.trackDeeplink(url: url)

        // handle airbridge deeplink
        var isHandled = Airbridge.handleDeeplink(url: url) { url in
            DeeplinkHandler.handleSchemeDeeplink(url: url)
        }
        if isHandled { return isHandled }

        // handle scheme deeplink
        isHandled = DeeplinkHandler.handleSchemeDeeplink(url: url)
        if isHandled { return isHandled }

        // handle other deeplink
        isHandled = DeeplinkHandler.handleOtherDeeplink(url: url)

        return isHandled
    }

    // when app is opened with universal links
    func application(
        _ application: UIApplication,
        continue userActivity: NSUserActivity,
        restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void
    ) -> Bool {
        // track deeplink
        Airbridge.trackDeeplink(userActivity: userActivity)

        // handle airbridge deeplink
        var isHandled = Airbridge.handleDeeplink(userActivity: userActivity) { url in
            DeeplinkHandler.handleSchemeDeeplink(url: url)
        }
        if isHandled { return isHandled }

        // handle other deeplink
        if let url = userActivity.webpageURL {
            isHandled = DeeplinkHandler.handleOtherDeeplink(url: url)
        }

        return isHandled
    }
}
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152
#import "AppDelegate.h"
#import "ABDeeplinkHandler.h"
#import <Airbridge/Airbridge.h>

@interface AppDelegate ()

@end

@implementation AppDelegate

// when app is opened with scheme deeplink
- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options {
    // track deeplink
    [Airbridge trackDeeplinkWithUrl:url];

    // handle airbridge deeplink
    BOOL isHandled = [Airbridge handleDeeplinkWithUrl:url onSuccess:^(NSURL* url) {
        [ABDeeplinkHandler handleSchemeDeeplink:url];
    }];
    if (isHandled) { return isHandled; }
    
    // handle scheme deeplink
    isHandled = [ABDeeplinkHandler handleSchemeDeeplink:url];
    if (isHandled) { return isHandled; }
    
    // handle other deeplink
    isHandled = [ABDeeplinkHandler handleOtherDeeplink:url];
    
    return isHandled;
}

// when app is opened with universal links
- (BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(void (^)(NSArray<id<UIUserActivityRestoring>> * _Nullable))restorationHandler {
    // track deeplink
    [Airbridge trackDeeplinkWithUserActivity:userActivity];

    // handle airbridge deeplink
    BOOL isHandled = [Airbridge handleDeeplinkWithUserActivity:userActivity onSuccess:^(NSURL* url) {
        [ABDeeplinkHandler handleSchemeDeeplink:url];
    }];
    if (isHandled) { return isHandled; }
    
    // handle other deeplink
    NSURL* url = userActivity.webpageURL;
    if (url != nil) {
        isHandled = [ABDeeplinkHandler handleOtherDeeplink:url];
    }
    
    return isHandled;
}

@end

Airbridge.handleDeeplink 함수는 에어브릿지 딥링크가 입력되면 true를 반환하고 Scheme 딥링크로 변환하여 onSuccess에 전달합니다. 그리고 에어브릿지 딥링크가 아닌 URL이 입력되거나 SDK가 초기화되지 않았으면 false를 반환하기만 합니다.

SDK를 초기화하는 부분에서Airbridge.handleDeferredDeeplink 함수를 호출합니다. onSuccess 콜백에서 에어브릿지로 실행된 스킴 딥링크를 처리하는 함수를 호출합니다.

1234567891011
import Airbridge
...
let option = AirbridgeOptionBuilder(name: "YOUR_APP_NAME", token: "YOUR_APP_SDK_TOKEN")
    .build()
Airbridge.initializeSDK(option: option)
...
let isHandled = Airbridge.handleDeferredDeeplink() { url in
    if let url {
        DeeplinkHandler.handleSchemeDeeplink(url)
    }
}
123456789101112
#import <Airbridge/Airbridge.h>
...
AirbridgeOptionBuilder* optionBuilder = [[AirbridgeOptionBuilder alloc] initWithName:@"YOUR_APP_NAME"
                                                                               token:@"YOUR_APP_SDK_TOKEN"];
AirbridgeOption* option = [optionBuilder build];
[Airbridge initializeSDKWithOption:option];
...
[Airbridge handleDeferredDeeplinkOnSuccess:^(NSURL* url) {
    if (url != nil) {
        [ABDeeplinkHandler handleSchemeDeeplink:url];
    }
}];

Airbridge.handleDeferredDeeplink 함수는 에어브릿지 딥링크가 입력되면 true와 함께 에어브릿지 딥링크 획득을 기다리거나 스킴 딥링크로 변환해 onSuccess로 전달합니다. 해당 스킴 딥링크를 활용해 유저를 설정한 목적지로 보낼 수 있습니다.

또는 저장된 에어브릿지 딥링크가 없으면 nil을 전달합니다. SDK가 초기화되지 않았거나 Airbridge.handleDeferredDeeplink 함수를 처음으로 호출하지 않았다면 false를 전달합니다.

커스텀 도메인을 등록하는 방법이 변경되었습니다. 기존에는 Info.plist의 co.ab180.airbridge.trackingLink.customDomains 키에 커스텀 도메인을 밸류로 추가했습니다.

변경된 방식은 SDK 초기화 단계에서 setTrackingLinkCustomDomains 함수를 호출하여 추가하는 방식입니다.

SDK 초기화 코드에서 setTrackingLinkCustomDomains 함수를 호출해 주세요.

12345678910
import Airbridge
...
// YOUR_APP_NAME: input your app name
// YOUR_APP_SDK_TOKEN: input your app token
// YOUR_APP_CUSTOM_DOMAIN: input your app custom domain. ex) example.domain.com
let option = AirbridgeOptionBuilder(name: "YOUR_APP_NAME",
                                    token: "YOUR_APP_SDK_TOKEN")
    .setTrackingLinkCustomDomains(["YOUR_APP_CUSTOM_DOMAIN"])
    .build()
Airbridge.initializeSDK(option: option)
12345678910
#import <Airbridge/Airbridge.h>
...
// YOUR_APP_NAME: input your app name
// YOUR_APP_SDK_TOKEN: input your app token
// YOUR_APP_CUSTOM_DOMAIN: input your app custom domain. ex) example.domain.com
AirbridgeOptionBuilder* optionBuilder = [[AirbridgeOptionBuilder alloc] initWithName:@"YOUR_APP_NAME"
                                                                               token:@"YOUR_APP_SDK_TOKEN"];
[optionBuilder setTrackingLinkCustomDomains:@[@"YOUR_APP_CUSTOM_DOMAIN"]];
AirbridgeOption* option = [optionBuilder build];
[Airbridge initializeSDKWithOption:option];

인앱 이벤트 및 유저 정보

주의하세요

기존 totalValue 대신 AirbridgeAttribute.VALUE에 값을 입력해 주세요.

setSemantics의 totalValue를 사용하고 setValue로 밸류를 정의하면 totalValue가 밸류를 덮어 쓰는 로직은 iOS SDK v4부터 삭제되었습니다.

ABInAppEvent 클래스가 Airbridge.trackEvent 함수로 대체되었습니다.

아래 가이드에 따라 ABInAppEvent 클래스와 setAction, setLabel, setValue, setSemantics, setCustoms를 Airbridge.trackEvent함수로 변경해 주세요.

  • setCategory: ABCategory를 사용하고 있다면 AirbridgeCategory를 사용해야 합니다. String을 사용하고 있다면 그대로 category 파라미터에 입력합니다.

  • setAction: semanticAttributes 파라미터의 AirbridgeAttribute.ACTION 키에 입력합니다.

  • setLabel: semanticAttributes 파라미터의 AirbridgeAttribute.LABEL 키에 입력합니다.

  • setValue: semanticAttributes 파라미터의 AirbridgeAttribute.VALUE 키에 입력합니다.

  • setSemantics: semanticAttributes 파라미터에 키로 ABSemanticsKey를 사용하고 있다면 AirbridgeAttribute를 사용합니다. String을 사용하고 있다면 그대로 입력합니다. 밸류는 키와 관계 없이 그대로 입력합니다.

  • setCustoms: customAttributes 파라미터에 키, 밸류를 그대로 입력합니다.

아래에서 AirbridgeCategory, AirbridgeAttribute 매핑과 Airbridge.trackEvent 함수를 참고해 주세요.

123456789101112131415161718192021222324252627282930
import Airbridge
...
// setCategory
Airbridge.trackEvent(
    category: AirbridgeCategory.ORDER_COMPLETED,
    semanticAttributes: [
        // setAction
        AirbridgeAttribute.ACTION: "Tool",
        // setLabel
        AirbridgeAttribute.LABEL: "Hammer",
        // setValue
        AirbridgeAttribute.VALUE: 10,
        // setSemantics (using ABSemanticsKey)
        AirbridgeAttribute.CURRENCY: "USD",
        AirbridgeAttribute.PRODUCTS: [
            [
                // setSemantics value (using ABProductKey)
                AirbridgeAttribute.PRODUCT_ID: "12345",
                // setSemantics value (using String)
                "name": "PlasticHammer",
            ],
        ],
        // setSemantics (using String)
        "totalQuantity": 1,
    ],
    customAttributes: [
        // setCustoms
        "promotion": "FirstPurchasePromotion",
    ]
)
12345678910111213141516171819202122232425
#import <Airbridge/Airbridge.h>
...
[Airbridge trackEventWithCategory:@"event" semanticAttributes:@{
    // action
    AirbridgeAttribute.ACTION: @"Tool",
    // label
    AirbridgeAttribute.LABEL: @"Hammer",
    // value
    AirbridgeAttribute.VALUE: @(10),
    // semantic attribute (provided by sdk)
    AirbridgeAttribute.CURRENCY: @"USD",
    AirbridgeAttribute.PRODUCTS: @[
        @{
            // semantic attribute value (provided by sdk)
            AirbridgeAttribute.PRODUCT_ID: @"12345",
            // semantic attribute value (not provided by sdk)
            @"name": @"PlasticHammer",
        },
    ],
    // semantic attribute (not provided by sdk)
    @"totalQuantity": @(1),
}, customAttributes:@{
    // custom attribute
    @"promotion": @"FirstPurchasePromotion",
}];

AirBridge.setDeviceAlias 관련 함수가 Airbridge.setDeviceAlias 관련 함수로 대체되었습니다.

12345
import Airbridge
...
Airbridge.setDeviceAlias(key: "string", value: "string")
Airbridge.removeDeviceAlias(key: "string")
Airbridge.clearDeviceAlias()
12345678910
#import <Airbridge/Airbridge.h>
...
BOOL isHandled = [Airbridge impressionWithTrackingLink:url onSuccess:^{
    // when url is tracking link and succeed
} onFailure:^(NSError * _Nonnull) {
    // when url is tracking link and failed
}];
if (!isHandled) {
    // when url is not tracking link
}

AirBridge.state().setUser 관련 함수가 Airbridge.setUser 관련 함수로 대체되었습니다. 유저 정보를 한번에 설정하는 setUser 함수는 지원하지 않습니다.

1234567891011121314151617181920
import Airbridge
...
// identifier
Airbridge.setUserID("string")
Airbridge.clearUserID()
// addtional identifier
Airbridge.setUserAlias(key: "string", value: "string")
Airbridge.removeUserAlias(key: "string")
Airbridge.clearUserAlias()
...
// email, phone
Airbridge.setUserEmail("string")
Airbridge.clearUserEmail()
Airbridge.setUserPhone("string")
Airbridge.clearUserPhone()
// addtional attribute
Airbridge.setUserAttribute(key: "string", value: "string")
Airbridge.setUserAttribute(key: "number", value: 1000)
Airbridge.removeUserAttribute(key: "string")
Airbridge.clearUserAttributes()
1234567891011121314151617181920
#import <Airbridge/Airbridge.h>
...
// identifier
[Airbridge setUserID:@"string"];
[Airbridge clearUserID];
// additional identifier
[Airbridge setUserAliasWithKey:@"string" value:@"string"];
[Airbridge removeUserAliasWithKey:@"string"];
[Airbridge clearUserAlias];
...
// email, phone
[Airbridge setUserEmail:@"string"];
[Airbridge clearUserEmail];
[Airbridge setUserPhone:@"string"];
[Airbridge clearUserPhone];
// addtional attribute
[Airbridge setUserAttributeWithKey:@"string" value:@"string"];
[Airbridge setUserAttributeWithKey:@"number" value:@(1000)];
[Airbridge removeUserAttributeWithKey:@"string"];
[Airbridge clearUserAttributes];

추가 설정하기

AirBridge.placement().click 함수와 AirBridge.placement().impression 함수가 Airbridge.click 함수와 Airbridge.impression 함수로 대체되었습니다.

1234567891011121314151617181920
import Airbridge
...
let isHandled = Airbridge.click(trackingLink: url) {
    // when url is tracking link and succeed
} onFailure: { error in
    // when url is tracking link and failed
    // example: url is another app's tracking link, internet is not connected
}
if !isHandled {
    // when url is not tracking link
}
...
let isHandled = Airbridge.impression(trackingLink: url) {
    // when url is tracking link and succeed
} onFailure: { error in
    // when url is tracking link and failed
}
if !isHandled {
    // when url is not tracking link
}
1234567891011121314151617181920
#import <Airbridge/Airbridge.h>
...
BOOL isHandled = [Airbridge clickWithTrackingLink:url onSuccess:^{
    // when url is tracking link and succeed
} onFailure:^(NSError * _Nonnull) {
    // when url is tracking link and failed
    // example: url is another app's tracking link, internet is not connected
}];
if (!isHandled) {
    // when url is not tracking link
}
...
BOOL isHandled = [Airbridge impressionWithTrackingLink:url onSuccess:^{
    // when url is tracking link and succeed
} onFailure:^(NSError * _Nonnull) {
    // when url is tracking link and failed
}];
if (!isHandled) {
    // when url is not tracking link
}

AirBridge.webInterface().inject 함수가 Airbridge.setWebInterface 함수로 대체되었습니다.

123456
import Airbridge
...
Airbridge.setWebInterface(
    controller: controller,
    webToken: "YOUR_WEB_TOKEN"
)
123
#import <Airbridge/Airbridge.h>
...
[Airbridge setWebInterfaceWithController:controller webToken:@"YOUR_WEB_TOKEN"];

v1.x 업데이트

iOS SDK 각 버전의 주요 변경사항을 참고해 주세요.

v1.36.0 - 딥링크

2023년 9월 4일 이후 생성된 에어브릿지 앱은 딥링크 콜백에서 제공되는 딥링크 URL이 에어브릿지 대시보드에 입력된 내용을 2번 디코딩해 제공하는 문제를 해결했습니다.

해당 문제는 iOS SDK v1.34.0 ~ 1.35.1에서 발생했습니다.

v1.34.0 - 딥링크

2023년 9월 4일 이후 생성된 에어브릿지 앱은 딥링크 콜백에 제공되는 딥링크 URL에 airbridge_referrer를 추가하지 않고 에어브릿지 대시보드에 입력한 정보로 전달됩니다.

2023년 9월 4일 이전에 생성된 에어브릿지 앱을 사용하는 고객사 중에서 해당 기능이 필요한 고객사는 에어브릿지 CSM에게 요청해 주세요. 담당 CSM이 없는 경우 문의하기를 통해 요청해 주세요.

v1.33.0 - SKAdNetwork

SKAdNetwork 4.0을 지원하면서 전환값 계산 방식이 변경되었습니다. 유저가 iOS SDK v1.33.0 미만을 설치한 앱에서 v1.33.0 이상이 있는 앱으로 업데이트하면 마지막에 계산된 전환값을 최종 값으로 확정합니다.

v1.32.1 - 개인정보보호 설정

trackingAuthorizeTimeout의 기본 설정이 0초에서 30초로 변경되었습니다.