Polyv Help Center

Help Center

7_6-核心common-互动

Updated: 2023-04-27 09:43:40

1 Feature Overview

This module is located under the folder PolyvLiveCommonModule/Modules/Interact. It is a functional module that can be shared across multiple scenarios, containing the following interactive apps: Announcement, Check-in, Lottery, Quiz, and Questionnaire. It encapsulates the interaction between the SDK layer PLVInteractWebview and the JS bridge PLVJSBridge, making the integration of interactive features simpler and more convenient. The core class PLVInteractView is used for integration.

The interactive module requires logging into the socket. When creating the chat module, the socket is automatically logged in by default. Therefore, it is recommended to integrate the chat module first when integrating interactive features. If the chat module is not needed, ensure that the socket login is handled in advance.

2 Socket Login and Logout

First, import the header file #import <PLVLiveScenesSDK/PLVSocketManager.h>. The login code example is as follows:

// 获取登录参数
PLVRoomData *roomData = [PLVRoomDataManager sharedManager].roomData;
PLVRoomUser *roomUser = roomData.roomUser;
        
// 功能配置
// 是否允许使用分房间功能,优先级高于后台的配置,默认为NO-不允许
[PLVSocketManager sharedManager].allowChildRoom = allow;

// Socket 登录管理
PLVSocketUserType userType = [PLVRoomUser sockerUserTypeWithRoomUserType:roomUser.viewerType];
[[PLVSocketManager sharedManager] loginWithChannelId:roomData.channelId viewerId:roomUser.viewerId viewerName:roomUser.viewerName avatarUrl:roomUser.viewerAvatar actor:nil userType:userType];

Second, you need to listen to the callbacks of the socket module. Follow the protocol PLVSocketManagerProtocol and add the listener code example as follows:

[[PLVSocketManager sharedManager] addDelegate:self delegateQueue:dispatch_get_main_queue()];

In the code example, passing delegateQueue as the parameter dispatch_get_main_queue() indicates that the callback method should be executed on the main thread. The socket module's login success and failure callbacks are as follows:

#pragma mark - PLVSocketManager Protocol

/// socket 登录成功回调
- (void)socketMananger_didLoginSuccess:(NSString *)ackString {
    // 可显示socket 登录成功提示
}

/// socket 登录失败回调
- (void)socketMananger_didLoginFailure:(NSError *)error {
    // 可弹出 socket 登录失败弹窗
}

Finally, when leaving the live room page, you need to log out of the socket module. The code example is as follows:

[[PLVSocketManager sharedManager] logout];

3 Core Class Introduction

The code is as follows:

PLVInteractView *interactView = [[PLVInteractView alloc] init];
interactView.frame = self.view.bounds;
/// 加载在线 互动页面
[interactView loadOnlineInteract];
/// 显示公告
[interactView openLastBulletin];

For specific usage, please refer to the calls to the PLVInteractView interface in PLVLCCloudClassViewController and PLVECWatchRoomViewController.

3.1 Public API Introduction

PLVInteractView defines the following methods that need to be used on the page:

/// 互动视图
///
/// @note 支持 ’答题卡、公告、抽奖、问卷、签到‘;
///       依赖于Socket模块正常运作,若互动视图异常,请先确认Socket已正确连接;
///       添加至相应视图中,并调用加载方法即可;
@interface PLVInteractView : UIView

/// 此时是否不允许转屏 (默认NO;接收到不同互动消息时,此值将根据业务要求,相应地变化)
@property (nonatomic, assign, readonly) BOOL forbidRotateNow;

/// 是否保持互动视图在同级视图中最顶层
///
/// @note 互动视图需要最顶层,才能保证接收到最新互动时,可完整地被用户查看
///      (YES:每次互动出现时,自动移至同级最顶层 NO:每次互动出现时,不做层级上的变动;默认为YES)
@property (nonatomic, assign) BOOL keepInteractViewTop;

- (void)openLastBulletin;

#pragma mark - 页面加载
/// 加载在线 互动页面
///
/// @note 为避免自动布局的警告,需在调用此方法前,设置 PLVInteractView 的frame值
- (void)loadOnlineInteract;

/// 加载本地 互动页面
///
/// @param htmlString 本地 html 解析后内容
/// @param baseURL 可访问的文件夹路径 (注意是 file:// 开头的 URL)
- (void)loadLocalInteractWithHTMLString:(NSString *)htmlString baseURL:(NSURL *)baseURL;
    
@end

3.2 Implementation Introduction

PLVInteractView internally implements the logic of interactive apps:

3.2.1 Initialization
- (instancetype)initWithFrame:(CGRect)frame{
    if (self = [super initWithFrame:frame]) {
        /// 初始化数据
        [self setupData];
        /// 初始化UI
        [self setupUI];
        /// 初始化互动应用
        [self setupInteractApps];
    }
    return self;
}
  • Initialize Data

In the setupData method, keepInteractViewTop indicates whether the interactive view needs to be at the topmost layer to ensure that the latest interaction can be fully viewed by the user. YES: Automatically move to the topmost layer each time an interaction appears. NO: Do not change the layer level when an interaction appears. The default is YES.

- (void)setupData{
    self.keepInteractViewTop = YES;
}
  • Initialize UI

The setupUI method initializes the interactive app Webview PLVInteractWebview object. By setting PLVInteractWebview, it loads online and local resources.

- (void)setupUI{
    self.backgroundColor = [UIColor colorWithRed:0.0 green:0.0 blue:0.0 alpha:0.3];
    self.hidden = YES;
    
    self.interactWebview = [[PLVInteractWebview alloc]init];
    self.interactWebview.delegate = self;

    self.jsBridge.delegate = self;
    //self.jsBridge.debugMode = YES;
    
    [self.webview addSubview:self.closeBtn];
}
  • Set Specific Interactive Apps

setupInteractApps sets specific interactive apps, adding the required interactive apps.

3.2.2 Implementation of Interactive Apps

Setting interactive apps means adding the desired interactive apps. See the method: setupInteractApps

- (void)setupInteractApps{
    [self.jsBridge addJsFunctionsReceiver:self];
    [self.jsBridge addObserveJsFunctions:@[@"initWebview", @"closeWebview", @"linkClick"]];
    
    [self addInteractApp:[PLVInteractSignIn class] eventString:PLVSocketInteraction_onSignIn_about];/// 签到
    [self addInteractApp:[PLVInteractBulletin class] eventString:PLVSocketIOChatRoom_BULLETIN_EVENT];/// 公告
    [self addInteractApp:[PLVInteractLottery class] eventString:PLVSocketInteraction_onLottery_about];/// 抽奖
    [self addInteractApp:[PLVInteractAnswer class] eventString:PLVSocketInteraction_onTriviaCard_about];/// 答题卡
    [self addInteractApp:[PLVInteractQuestionnaire class] eventString:PLVSocketInteraction_onQuestionnaire_about];/// 问卷
}

- (void)addInteractApp:(Class)interactClass eventString:(NSString *)eventString{
    PLVInteractBaseApp * app = [[interactClass alloc] initWithJsBridge:self.jsBridge];
    app.delegate = self;
    [self.interactDict setObject:app forKey:eventString];
}

The logic of the setupInteractApps method is divided into two steps:

  1. Instantiate specific interactive apps and set the corresponding callbacks. Note that the general control is not a business-related interactive app; it is a general class used to control all interactive apps and must be added.

  2. Add all interactive apps to the interactive app webView.

4 Implementation of Interactive Apps

4.1 Interactive App Class Overview

The specific implementation of interactive apps is located in the PolyvLiveCommonModule/Modules/Interact directory, at the same level as PLVInteractView. There are 5 interactive apps, each class representing:

  • PLVInteractAnswer: Quiz
  • PLVInteractBulletin: Announcement
  • PLVInteractLottery: Lottery
  • PLVInteractQuestionnaire: Questionnaire
  • PLVInteractSignIn: Check-in

Other classes in this directory: PLVInteractBaseApp+General is an extension class of PLVInteractBaseApp in the SDK. This class primarily uses the SDK layer PLVSocketManager to send data to the server.

4.2 Specific Interactive App Implementation Logic

All 5 interactive apps inherit from PLVInteractBaseApp. PLVInteractBaseApp is mainly responsible for binding the JS bridge, sending data to the webView, and handling delegate callbacks.

The 5 interactive app subclasses handle their respective functionalities, assembling and sending data to the webView.

5 SDK Core Class Introduction

5.1 PLVInteractBaseApp

PLVInteractBaseApp is the base class for interactive apps. All interactive apps extend from this class as the parent class to implement their own business logic.

5.1.1 Subclass Override Methods

Methods that need to be overridden by specific interactive app subclasses.

/// 初始化
///
/// @param jsBridge PLVJSBridge对象
- (instancetype)initWithJsBridge:(PLVJSBridge *)jsBridge;

/// 接收互动应用信息
///
/// @param msgString 对象
/// @param jsonDict 对象
- (void)processInteractMessageString:(NSString *)msgString jsonDict:(NSDictionary *)jsonDict;
5.1.2 Delegate Callbacks
@protocol PLVInteractBaseAppDelegate <NSObject>
/// 互动应用旋转
- (void)plvInteractAppRequirePortraitScreen:(PLVInteractBaseApp *)interactApp;

/// 互动应用显示隐藏
///
/// @param show YES 显示,NO 隐藏
- (void)plvInteractApp:(PLVInteractBaseApp *)interactApp webviewShow:(BOOL)show;

@end
5.1.3 Methods Used by Subclasses

The parent class defines some common methods that can be called by interactive app subclasses.

/// 通知显示旋转
- (void)callRequirePortraitScreen;

/// 通知UI显示
- (void)callWebviewShow;

/// 发送数据到WebView
///
/// @param json 发送数据内容
/// @param event 事件名
- (void)submitResultCallback:(NSString *)json event:(NSString *)event;

/// 发送超时数据到WebView
///
/// @param event 事件名
- (void)submitResultTimeoutCallback:(NSString *)event;

5.2 PLVJSBridge

PLVJSBridge is the Webview JS interactor, used for data interaction with the Webview.

5.2.1 Public API Introduction
/// 添加对象作为接收者
///
/// @note 该接收者需要实现对应的Js方法
///
/// @param receiver JS方法回调的接收者
- (void)addJsFunctionsReceiver:(NSObject *)receiver;

/// 添加需要监听的Js方法回调
///
/// @note 需通过 [addJsFunctionsReceiver:] 添加对象作为接收者;该接收者需要实现对应的Js方法;满足以上条件,才能如期收到回调;
///
/// @param jsFunctions 需要监听的Js方法回调数组
- (void)addObserveJsFunctions:(NSArray <NSString *> *)jsFunctions;

#pragma mark - 页面加载
/// 加载在线 url 链接
///
/// @param url url链接
/// @param view 承载 webview 的父视图
- (void)loadWebView:(NSString *)url inView:(UIView *)view;

/// 加载本地 html 文件
///
/// @param htmlString 本地 html 解析后内容
/// @param baseURL 可访问的文件夹路径 (注意是 file:// 开头的 URL)
/// @param view 承载 webview 的父视图
- (void)loadHTMLString:(NSString *)htmlString baseURL:(NSURL *)baseURL inView:(UIView *)view;

/// 加载本地 html 文件
///
/// @note 该方法要求 iOS9 以上;对本地文件读取的兼容性更好
///
/// @param URL html 本地文件路径 (注意是 file:// 开头的 URL)
/// @param readAccessURL 可访问的文件夹路径 (注意是 file:// 开头的 URL)
/// @param view 承载 webview 的父视图
- (void)loadFileURL:(NSURL *)URL allowingReadAccessToURL:(NSURL *)readAccessURL inView:(UIView *)view API_AVAILABLE(ios(9.0));

#pragma mark - Js交互
/// 向 webview 注入 js 以调用方法
///
/// @param jsFunction js 方法名
/// @param params 需要传递的参数
- (void)call:(NSString *)jsFunction params:(NSArray *)params;

Examples of method API call code can be found in the subclasses PLVInteractView, PLVInteractBaseApp, and PLVInteractBaseApp.

5.2.2 Delegate Callbacks
@protocol PLVJSBridgeDelegate <NSObject>

@optional

/// webview 加载成功回调
///
/// @param jsBridge 当前对象本身
- (void)plvJSBridgeWebviewDidFinishLoad:(PLVJSBridge *)jsBridge;

/// webview 加载失败回调
///
/// @param jsBridge 当前对象本身
- (void)plvJSBridgeWebviewDidFailLoad:(PLVJSBridge *)jsBridge withError:(NSError *)error;

/// webview 需要展示或隐藏‘加载指示器’时,将触发此回调
///
/// @note 可通过此回调,来获知合适的时机,进行自定义加载指示器的展示或隐藏;
///       若需自定义加载指示器,请设置 [customActivityIndicator],设置YES后,内置加载指示器将不显示;
///
/// @param jsBridge 当前对象本身
/// @param loadingShow 是否需要展示或隐藏‘加载指示器’ (YES:需要展示 NO:需要隐藏)
- (void)plvJSBridge:(PLVJSBridge *)jsBridge webviewLodingShow:(BOOL)loadingShow;

/// webview 需要展示确认面板
///
/// @note 当此接收到此回调时,可弹出 UIAlertController 或 一个自定义确认弹窗
///
/// @param jsBridge 当前对象本身
/// @param message 需要展示的信息 (可作为 ‘确认弹窗’ 的提示语)
/// @param frame 发起弹窗的页面框架信息
/// @param completionHandler 当确认弹窗被点击后,需回调此Block并附带BOOL参数 (YES:用户选择‘好的’ NO:用户选择‘取消’)
- (void)plvJSBridge:(PLVJSBridge *)jsBridge showConfirmPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(BOOL result))completionHandler;

Examples of setting delegate callbacks can be found in the Demo's PLVInteractView.

联系客服,在线咨询