7_6-核心common-互动
1 功能概述
該模組位於資料夾 PolyvLiveCommonModule/Modules/Interact 下,是多個場景都可共用的功能模組,包含以下互動應用:公告、簽到、抽獎、答題卡和問卷,是對 SDK 層的 PLVInteractWebview 和 JS 橋 PLVJSBridge 的互動封裝,使整合互動功能更簡單方便。由 PLVInteractView 作為核心類別來整合。
互動模組需要登入 socket,在建立聊天模組時,已預設自動登入 socket,因此整合互動功能時,最好先整合聊天模組;若不需要聊天模組,請務必提前完成 socket 的登入。
2 socket 登入與登出
首先,匯入標頭檔 #import <PLVLiveScenesSDK/PLVSocketManager.h>,登入程式碼範例如下:
// 获取登录参数
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];
其次,需要監聽 socket 模組的回呼,遵循協定 PLVSocketManagerProtocol 並加入監聽程式碼範例如下:
[[PLVSocketManager sharedManager] addDelegate:self delegateQueue:dispatch_get_main_queue()];
程式碼範例中,delegateQueue 參數傳入 dispatch_get_main_queue() 表示希望回呼方法從主執行緒執行,socket 模組登入成功、失敗的回呼如下:
#pragma mark - PLVSocketManager Protocol
/// socket 登录成功回调
- (void)socketMananger_didLoginSuccess:(NSString *)ackString {
// 可显示socket 登录成功提示
}
/// socket 登录失败回调
- (void)socketMananger_didLoginFailure:(NSError *)error {
// 可弹出 socket 登录失败弹窗
}
最後,離開直播間頁面時,需要對 socket 模組進行登出,程式碼範例如下:
[[PLVSocketManager sharedManager] logout];
3 核心類別介紹
程式碼如下:
PLVInteractView *interactView = [[PLVInteractView alloc] init];
interactView.frame = self.view.bounds;
/// 加载在线 互动页面
[interactView loadOnlineInteract];
/// 显示公告
[interactView openLastBulletin];
具體的使用方法請參考 PLVLCCloudClassViewController、PLVECWatchRoomViewController 中對 PLVInteractView 介面的呼叫。
3.1 對外 API 介紹
PLVInteractView 定義了以下幾個需要在頁面中使用的方法:
/// 互动视图
///
/// @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 實作介紹
PLVInteractView 內部實作了互動應用的邏輯:
3.2.1 初始化
- (instancetype)initWithFrame:(CGRect)frame{
if (self = [super initWithFrame:frame]) {
/// 初始化数据
[self setupData];
/// 初始化UI
[self setupUI];
/// 初始化互动应用
[self setupInteractApps];
}
return self;
}
- 初始化資料
setupData 方法中 keepInteractViewTop 是互動檢視需要位於最上層,才能確保接收到最新互動時,可完整地被使用者檢視。YES:每次互動出現時,自動移至同層級最上層;NO:每次互動出現時,不做層級上的變動;預設為 YES。
- (void)setupData{
self.keepInteractViewTop = YES;
}
- 初始化 UI
setupUI 方法初始化互動應用 Webview PLVInteractWebview 物件,透過設定 PLVInteractWebview 載入線上、本地資源。
- (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];
}
- 設定具體的互動應用
setupInteractApps 設定具體的互動應用,將所需的互動應用加入。
3.2.2 互動應用的實作
設定互動應用即是將想要的互動應用加入。請見方法: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];
}
setupInteractApps 方法的邏輯分為兩步:
實例化具體的互動應用,並設定對應的回呼。請注意,通用控制不屬於業務上的互動應用,它是用於控制所有互動應用的一個通用類別,是必須加入的。
將所有互動應用加入互動應用 webView 中。
4 互動應用的實作
4.1 互動應用類別簡介
互動應用的具體實作位於 PolyvLiveCommonModule/Modules/Interact 目錄下,與 PLVInteractView 同級目錄,共有 5 個互動應用,每個類別分別表示:
- PLVInteractAnswer:答題
- PLVInteractBulletin:公告
- PLVInteractLottery:抽獎
- PLVInteractQuestionnaire:問卷
- PLVInteractSignIn:簽到
該目錄的其他類別:
PLVInteractBaseApp+General 是 SDK 中 PLVInteractBaseApp 的擴充類別,該類別主要使用 SDK 層的 PLVSocketManager 向伺服器端發送資料。
4.2 具體互動應用實作邏輯
5 個互動應用均繼承自 PLVInteractBaseApp,PLVInteractBaseApp 主要負責綁定 JS 橋、發送資料到 webView 以及與代理回呼。
5 個互動應用子類別分別處理各自功能,將組裝好的資料發送到 webView。
5 SDK 核心類別介紹
5.1 PLVInteractBaseApp
PLVInteractBaseApp 是互動應用基礎類別,所有互動應用都以該類別作為父類別進行擴展,以實現各自的業務邏輯。
5.1.1 子類別覆寫方法
需要具體的互動應用子類別覆寫的方法。
/// 初始化
///
/// @param jsBridge PLVJSBridge对象
- (instancetype)initWithJsBridge:(PLVJSBridge *)jsBridge;
/// 接收互动应用信息
///
/// @param msgString 对象
/// @param jsonDict 对象
- (void)processInteractMessageString:(NSString *)msgString jsonDict:(NSDictionary *)jsonDict;
5.1.2 代理回呼
@protocol PLVInteractBaseAppDelegate <NSObject>
/// 互动应用旋转
- (void)plvInteractAppRequirePortraitScreen:(PLVInteractBaseApp *)interactApp;
/// 互动应用显示隐藏
///
/// @param show YES 显示,NO 隐藏
- (void)plvInteractApp:(PLVInteractBaseApp *)interactApp webviewShow:(BOOL)show;
@end
5.1.3 子類別使用的方法
父類別中定義了一些通用方法,可供互動應用子類別呼叫。
/// 通知显示旋转
- (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 是 Webview JS 互動器,可用於與 Webview 進行資料互動。
5.2.1 對外 API 介紹
/// 添加对象作为接收者
///
/// @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;
方法 API 呼叫程式碼的範例可在 PLVInteractView、PLVInteractBaseApp 和 PLVInteractBaseApp 子類別中找到。
5.2.2 代理回呼
@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;
設定代理回呼的範例可在 Demo 的 PLVInteractView 中找到。
