Event handler

    Event handler


    기사 요약

    Shoplive Player에서 발생한 사용자 UI 이벤트 또는 상태 변경과 같은 알림을 클라이언트에서 핸들러(delegate) 함수를 통해 전달받고 필요한 처리를 합니다.


    delegate

    Shoplive iOS SDK의 핸들러 이벤트를 전달받는 함수를 선언하고, Shoplive iOS SDK와 이벤트를 연결하는 property입니다.

    @objc var delegate: ShopLiveSDKDelegate? { get set }
    @objc public protocol ShopLiveSDKDelegate: AnyObject {
        @objc func handleNavigation(with url: URL)
        @objc func handleChangeCampaignStatus(status: String)
        @objc optional func handleChangedPlayerStatus(status: String)
        @objc func handleCampaignInfo(campaignInfo: [String : Any])
    
        @objc func onSetUserName(_ payload: [String : Any])
    
        @objc func handleCommand(_ command: String, with payload: Any?)
        @objc func handleReceivedCommand(_ command: String, with payload: Any?)
    
        @objc func handleError(code: String, message: String)
    
        @objc optional func handleDownloadCoupon(with couponId: String, result: @escaping (ShopLiveCouponResult) -> Void)
        @objc optional func handleCustomAction(with id: String, type: String, payload: Any?, result: @escaping (ShopLiveCustomActionResult) -> Void)
        @objc optional func playerPanGesture(state: UIGestureRecognizer.State, position: CGPoint)
        @objc optional func log(name: String, feature: ShopLiveLog.Feature, campaign: String, payload: [String: Any])
    
    }

    Sample code

    class MainViewController: UIViewController {
        ...
        override func viewDidLoad() {
            super.viewDidLoad()
    
            // delegate와 현재 클래스를 연결합니다.
            ShopLive.delegate = self
    
        }
        ...
    }
    
    // delegate를 연결할 클래스는 ShopLiveSDKDelegate Protocol을 구현합니다. 
    extension MainViewController: ShopLiveSDKDelegate {
        func handleNavigation(with url: URL) {
            print("handleNavigation \(url)")
        }
        ...
    }


    handleNavigation

    Shoplive에서 상품, 배너 등을 선택(탭) 했을 때, 선택한 상품 또는 배너 정보를 전달합니다.

    handleNavigation(with url: URL)

    Parameter name

    Type

    Description

    url

    URL

    상품 또는 배너 선택 시 이동할 URL

    Sample code

    extension MainViewController: ShopLiveSDKDelegate {
        func handleNavigation(with url: URL) {
            print("handleNavigation \(url)")
    
            UIApplication.shared.open(url, options: [:], completionHandler: nil)
        }
        ...
    }


    handleChangeCampaignStatus

    방송 상태가 변경되었을 때 변경된 방송 상태를 전달합니다.

    @objc func handleChangeCampaignStatus(status: String)

    Parameter name

    Type

    Description

    Status

    String

    방송 상태: READY, ONAIR, CLOSED

    Sample code

    extension MainViewController: ShopLiveSDKDelegate {
        func handleChangeCampaignStatus(status: String) {
            print("handleChangeCampaignStatus \(status)")
    
            switch status {
                case "READY", "ONAIR":
                    break
                case "CLOSED":
                    print("ended campaign")
                    break
            }
        }
        ...
    }


    handleChangedPlayerStatus

    Shoplive Player 상태를 전달 받습니다.

    handleChangedPlayerStatus(status: String)

    Parameter name

    Type

    Description

    Status

    String

    Shoplive Player 상태:

    • CREATED : 플레이어 생성됨

    • DESTROYE : 플레이어 종료됨

    Sample code

    extension MainViewController: ShopLiveSDKDelegate {
        func handleChangedPlayerStatus(status: String) {
            print("handleChangedPlayerStatus \(status)")
    
            switch status {
                case "CREATED":
                    break
                case "DESTROYED":
                    break
            }
        }
        ...
    }


    handleCampaignInfo

    현재 방송에 관한 정보를 전달합니다.

    handleCampaignInfo(campaignInfo: [String : Any])

    Parameter name

    Type

    Description

    campaignInfo

    [String : Any]

    현재 방송의 정보

    • 예) title: 방송 제목

    Sample code

    extension MainViewController: ShopLiveSDKDelegate {
        func handleCampaignInfo(campaignInfo: [String : Any]) {
    
            campaignInfo.forEach { (key, value) in
                print("campaignInfo key: \(key)  value: \(value)")
            }
    
        }
        ...
    }


    onSetUserName

    사용자 이름이 변경되었을 때 호출됩니다.

    onSetUserName(_ payload: [String : Any])

    Parameter name

    Type

    Description

    payload

    [String : Any]

    사용자 정보

    예: userId(사용자 ID)

    Sample code

    extension MainViewController: ShopLiveSDKDelegate {
        func onSetUserName(_ payload: [String : Any]) {
            payload.forEach { (key, value) in
                print("onSetUserName key: \(key) value: \(value)")
            }
        }
        ...
    }


    handleReceivedCommand

    Shoplive iOS SDK의 WEB으로부터 수신된 명령어 정보를 전달합니다.

    handleReceivedCommand(_ command: String, with payload: Any?)

    Parameter name

    Type

    Description

    command

    String

    명령어 이름

    payload

    Any?

    명령어와 함께 전달되는 데이터

    Sample code

    extension MainViewController: ShopLiveSDKDelegate {
        func handleReceivedCommand(_ command: String, with payload: Any?) {
            switch command {
            case "LOGIN_REQUIRED":
                let alert = UIAlertController(title: command, message: "alert.login.required.description".localized(), preferredStyle: .alert)
                alert.addAction(.init(title: "alert.msg.ok".localized(), style: .default, handler: { _ in
                    /*
                        1. 로그인 화면으로 이동
                        2. 로그인이 성공하면, 인증 사용자 계정을 연동하여 샵라이브플레이어를 다시 호출
                     */
                    ShopLive.startPictureInPicture()
                    let login = LoginViewController()
                    login.delegate = self
                    self.navigationController?.pushViewController(login, animated: true)
                }))
                alert.addAction(.init(title: "alert.msg.no".localized(), style: .default, handler: { _ in
                    alert.dismiss(animated: true)
                }))
                ShopLive.viewController?.present(alert, animated: true, completion: nil)
                break
            case "CLICK_PRODUCT_CART":
              break
            default:
                break
            }
          
        }
        ...
    }

    Shoplive Player 상태 변경

    Shoplive Player 상태가 변경될 때 commandShopLiveViewTrackEvent를 전달합니다.

    ShopLiveViewTrackEvent

    @objc public enum ShopLiveViewTrackEvent : Int, CaseIterable {
        case viewWillDisAppear
        case viewDidDisAppear
        case pipWillAppear
        case pipDidAppear
        case fullScreenWillAppear
        case fullScreenDidAppear
        
        public var name : String {
            switch self {
            case .viewWillDisAppear:
                return "viewWillDisAppear"
            case .viewDidDisAppear:
                return "viewDidDisAppear"
            case .pipWillAppear:
                return "pipWillAppear"
            case .pipDidAppear:
                return "pipDidAppear"
            case .fullScreenWillAppear:
                return "fullScreenWillAppear"
            case .fullScreenDidAppear:
                return "fullScreenDidAppear"
            }
        }
    }

    Parameter name

    Type

    Description

    viewWillDisAppear

    CaseIterable

    Shoplive Player가 종료 상태로 변경 시작

    viewDidDisAppear

    CaseIterable

    Shoplive Player가 종료 상태로 변경 완료

    pipWillAppear

    CaseIterable

    Shoplive Player가 PIP 모드 상태로 변경 시작

    pipDidAppear

    CaseIterable

    Shoplive Player가 PIP 모드 상태로 변경 완료

    fullScreenWillAppear

    CaseIterable

    Shoplive Player가 전체화면 모드 상태로 변경 시작

    fullScreenDidAppear

    CaseIterable

    Shoplive Player가 전체화면 모드 상태로 변경 완료

    payload

    변경 전 Shoplive Player 상태를 payload로 전달합니다.

    Parameter name

    Type

    Description

    currentStyle

    Any?

    현재 PresentationStyle의 name (String)

    lastStyle

    Any?

    현재 PresentationStyle의 name (String)

    isPreview

    Any?

    preview인지 inAppPip인지의 여부 (Optional Bool)

    viewHiddenActionType

    Any?

    ShopLiveViewHiddenActionType (Optional String)

    • onSwipeOut: Preview를 쓸어넘겨서 종료

    • onBtnTapped: 뒤로가기 버튼을 눌러서 종료

    • onClose: close()함수를 호출해서 종료

    • onError: 오류로 인한 종료

    • onRestoringPip: Pip에서 앱으로 복귀시 에러로 종료

    • onNavigationHandleClose: 사용자가 nextActionTypeOnHandleNavigation의 정의를 .CLOSE로 했을때 종료

    Deprecated

    ShopLiveViewTrackEvent

    Parameter name

    Type

    Description

    willShopLiveOn

    CaseIterable

    Shoplive Player가 전체 화면으로 변경 시작

    didShopLiveOn

    CaseIterable

    Shoplive Player가 전체 화면으로 변경 완료

    willShopLiveOff

    CaseIterable

    Shoplive Player가 PIP 모드 또는 종료 상태로 변경 시작

    didShopLiveOff

    CaseIterable

    Shoplive Player가 PIP 모드 또는 종료 상태로 변경 완료

    payload

    Parameter name

    Type

    Description

    style

    Any?

    PresentationStyle의 rawValue (Int)

    Sample code

    extension MainViewController: ShopLiveSDKDelegate {
        func handleCommand(_ command: String, with payload: Any?) {
            print("handleCommand: \(command)  payload: \(payload)") 
        }
        ...
    }


    Coupon

    쿠폰 처리를 완료할 때 쿠폰 활성 여부를 설정하기 위한 상태입니다.

    @objc public enum ShopLiveResultStatus: Int, CaseIterable {
        case SHOW // 쿠폰 다시 활성
        case HIDE // 쿠폰 사라짐
        case KEEP // 상태 유지
    
        public var name: String {
            switch self {
            case .SHOW:
                return "SHOW"
            case .HIDE:
                return "HIDE"
            case .KEEP:
                return "KEEP"
            }
        }
    }

    쿠폰 처리를 완료할 때 알림 메시지가 있으면 나타나는 타입을 설정합니다.

    @objc public enum ShopLiveResultAlertType: Int, CaseIterable {
        case ALERT // 얼럿
        case TOAST // 토스트
    
        public var name: String {
            switch self {
            case .ALERT:
                return "ALERT"
            case .TOAST:
                return "TOAST"
            }
        }
    }

    @objc public class ShopLiveCouponResult: NSObject {
        var success: Bool         // 쿠폰 처리 성공/실패 여부
        var coupon: String = ""   // 쿠폰 ID
        var message: String?      // 알림 메시지
        var couponStatus: ShopLiveResultStatus // 완료 후 쿠폰 상태
        var alertType: ShopLiveResultAlertType // 알림 메시지 출력 타입
    
        public init(couponId: String, success: Bool, message: String?, status: ShopLiveResultStatus, alertType: ShopLiveResultAlertType) {
            self.coupon = couponId
            self.success = success
            self.message = message
            self.couponStatus = status
            self.alertType = alertType
        }
    }

    @objc public class ShopLiveCustomActionResult: NSObject {
        var success: Bool             // 커스텀 동작 처리 성공/실패
        var id: String = ""           // 커스텀 동작 ID   
        var message: String?          // 알림 메시지
        var couponStatus: ShopLiveResultStatus           // 완료 후 커스텀 동작 상태
        var alertType: ShopLiveResultAlertType           // 알림 메시지 출력 타입
    
        public init(id: String, success: Bool, message: String?, status: ShopLiveResultStatus, alertType: ShopLiveResultAlertType) {
            self.id = id
            self.success = success
            self.message = message
            self.couponStatus = status
            self.alertType = alertType
        }
    }


    handleDownloadCoupon

    Shoplive에서 쿠폰을 선택(탭) 했을 때 클라이언트로 쿠폰 정보를 전달합니다. 클라이언트의 쿠폰 처리 결과를 Shoplive iOS SDK로 다시 전달하는 result callback을 통해 Shoplive Player에서의 쿠폰 상태를 설정합니다.

    handleDownloadCoupon(with couponId: String, result: @escaping (ShopLiveCouponResult) -> Void)

    Parameter name

    Type

    Description

    couponId

    String

    쿠폰 ID

    result

    ShopLiveCouponResult

    결과값을 Shoplive iOS SDK로 전달하는 result callback

    Sample code

    extension MainViewController: ShopLiveSDKDelegate {
        func handleDownloadCoupon(with couponId: String, result: @escaping (ShopLiveCouponResult) -> Void) {
            print("handleDownloadCoupon: \(couponId)")
    
            //쿠폰 처리 완료 시 호출 (처리 결과)
            // 성공
            let couponResult = ShopLiveCouponResult(couponId: couponId, success: true, message: "쿠폰 다운로드가 성공하였습니다.", status: .SHOW, alertType: .ALERT)
            // 실패
            let couponResult = ShopLiveCouponResult(couponId: couponId, success: false, message: "쿠폰 다운로드가 실패하였습니다.", status: .HIDE, alertType: .TOAST)
            result(couponResult)
        }
        ...


    handleCustomAction

    팝업에서 클릭 이벤트를 custom으로 지정하고, 팝업을 선택(탭) 했을 때 팝업 정보를 전달합니다. 팝업의 idtype (COUPONBANNERNOTICE), payload를 전달합니다.

    handleCustomAction(with id: String, type: String, payload: Any?, result: @escaping (ShopLiveCustomActionResult) -> Void)

    Parameter name

    Type

    Description

    id

    String

    팝업 ID

    type

    String

    팝업 타입: COUPON, BANNER, NOTICE

    payload

    Any?

    사용자 정의 데이터

    result

    ShopLiveCustomActionResult

    결과값을 Shoplive iOS SDK로 전달하는 result callback

    Sample code

    extension MainViewController: ShopLiveSDKDelegate {
        func handleCustomAction(with id: String, type: String, payload: Any?, result: @escaping (ShopLiveCustomActionResult) -> Void) {
            print("handleCustomAction \(id) \(type) \(payload.debugDescription)")
    
            // 팝업 처리가 완료되면 호출됨(처리 결과)
            // 성공
            let customActionResult = ShopLiveCustomActionResult(id: id, success: true, message: "Coupon download was successful.", status: .SHOW, alertType: .ALERT)
    
            // 실패
            let customActionResult = ShopLiveCustomActionResult(id: id, success: false, message: "Coupon download was failed.", status: .HIDE, alertType: .TOAST)
    
            result(customActionResult)
        }
        ...
    }
    


    handleError

    방송 전 또는 방송 중 발생하는 오류 상황에 관한 메시지를 전달합니다.

    handleError(code: String, message: String)

    Parameter name

    Type

    Description

    code

    String

    오류 코드

    message

    String

    오류 메시지

    Sample code

    extension MainViewController: ShopLiveSDKDelegate {
        func handleError(code: String, message: String) {
            print("handleError \(code) \(message)")
        }
        ...
    }


    playerPanGesture

    PIP모드에서 창 위치를 움직일때, 창의 좌표와 제스쳐이벤트 상태를 전달합니다.

    playerPanGesture(state: UIGestureRecognizer.State, position: CGPoint)

    Sample code

    extension MainViewController: ShopLiveSDKDelegate {
    	func playerPanGesture(state: UIGestureRecognizer.State, position: CGPoint) {
        	print("gesture state \(state) position \(position)")
    	}
      ...
    }


    onEvent

    Shoplive Player의 이벤트 로그를 전달합니다. 이 정보는 Google Analytics 등의 분석 도구에서 사용할 수 있습니다.

    onEvent(name: String, feature: ShopLiveLog.Feature, campaign: String, payload: [String: Any])

    ShopLiveLog

    Shoplive Player의 이벤트 로그를 전달합니다. 이 정보는 Google Analytics 등의 분석 도구에서 사용할 수 있습니다.

    @objc public class ShopLiveLog: NSObject {
        @objc public enum Feature: Int, CaseIterable {
            case CLICK, SHOW, ACTION
            
            public var name: String {
                switch self {
                case .CLICK:
                    return "click"
                case .ACTION:
                    return "action"
                case .SHOW:
                    return "show"
                }
            }
            
            static func featureFrom(type: String) -> Feature? {
                return Feature.allCases.filter({$0.name == type}).first
            }
        }
        
        public var name: String
        public var campaign: String
        public var feature: Feature
        public var payload: [String: Any] = [:]
        
        public init(name: String, feature: Feature, campaign: String, payload: [String : Any]) {
            self.name = name
            self.feature = feature
            self.campaign = campaign
            self.payload = payload
        }
    }

    Sample code

    extension MainViewController: ShopLiveSDKDelegate {
        func onEvent(name: String, feature: ShopLiveLog.Feature, campaign: String, payload: [String : Any]) {
            let eventLog = ShopLiveLog(name: name, feature: feature, campaign: campaign, payload: payload)
            print("eventLog \(eventLog.name)")
        }
    }


    What's Next