观看文档准备

  1. 注册微吼开发者账号

  2. 创建应用 获取AppID

  3. 设置应用Bundle ID

  4. 获取 频道ID channelID

    可以通过 【测试工具】 或 【API】 获得

  5. 获取包含文档权限的access_token

    可以通过 【测试工具】 或 【API】 获得

工程配置

在开始使用sdk之前,我们要配置好IDE和创建基础的工程代码。相关内容在【工程配置】中有详细说明。

对接流程

1: 引入文档模块头文件

#import "VHDocument.h"

2: 创建Document

SDK 中的 VHDocument 模块负责实现 文档服务相关功能。

  1. 直播文档模块初始化 获取channelID和accessToken 参考页首观看文档准备
NSString* channelID = @"xxxxxx";
NSString* accessToken = @"xxxxxxxxxx";
_document = [[VHDocument alloc]initWithChannelID:channelID accessToken:accessToken];
  1. 直播+文档模式初始化 获取channelID、roomID和accessToken 参考页首观看文档准备 roomID,直播房间ID,用于生成回放时文档回放播放
/**
 * 直播+文档模块初始化
 */
- (instancetype)initWithChannelID:(NSString*)channelID roomID:(NSString*)roomID accessToken:(NSString*)accessToken;

3: 设置 渲染View、delegate

  • delegate 设置文档代理
  • 注意:view大小设置 需同一个 频道的 安卓端,JS SDK端 保持 宽高比一致,否则画笔在各端显示位置会有偏差
  • 接下来我们要给文档画面找个地方来显示,iOS系统中使用 view 作为基本的界面渲染单位,所以您只需要准备一个 view 并调整好布局就可以了。
_document.delegate = self;
_document.view.frame = self.view.bounds;
[self.view insertSubview:_document.view atIndex:0];

3: 设置演示端模式

  • view.editEnable 设置演示端模式
  • 现一个channelID只允许一个演示端,多端演示待以后版本迭代
_document.view.editEnable = YES;

4: 设置演示文档

  • documentID 通过微吼云控制台上传文档获得
NSString* documentID = @"xxxxxxxxxx";
[_document setDocWithID:documentID];

5: 演示文档操作相关接口

- (void)prevPage;//上一页
- (void)nextPage;//下一页
- (void)prevStep;//上一步
- (void)nextStep;//下一步
- (void)gotoPage:(int) page;//跳转至第几页
- (void)gotoPage:(int) page step:(int)step;//跳转至第几步

6: 涂鸦操作相关接口

/*
 * 是否开启涂鸦模式
 */
@property (nonatomic,assign)BOOL    editGraffitEnable;
/*
 * 绘制命令类型
 */
@property (nonatomic,assign)VHDrawAction  drawAction;

/*
 * 绘制类型
 * 注意:设置此参数时  editType 自动设置为 VHEditType_Add 模式
 */
@property (nonatomic,assign)VHDrawType  drawType;

/*
 * 设置颜色、大小
 */
- (void)setColor:(UIColor*)color;

/*
 * 大小
 */
- (void)setSize:(NSInteger)size;

/*
 * 清空
 */
- (void)clear;

事件处理

SDK 通过 VHDocumentDelegate 代理来监听文档相关事件

具体 VHDocumentDelegate 中方法参考【文档模块参考手册

/*
 *  documentView Load完成 完成后
 */
- (void)documentViewDidLoad;

/**
 *  直播文档同步
 *  @param document 文档实例
 *  @param channelID   文档channelID
 *  @return float   延迟执行时间 即直播延迟时间 realityBufferTime
 */
- (float)document:(VHDocument *)document delayChannelID:(NSString*)channelID;

/**
 *  翻页消息
 *  @param document 文档实例
 *  @param documentID   文档id 为空时没有 文档
 *  @param curPage  当前页码 0开始
 */
- (void)document:(VHDocument *)document documentID:(NSString*) documentID curPage:(int)curPage;

/**
 *  错误回调
 *  @param document 文档实例
 *  @param error    错误
 */
- (void)document:(VHDocument *)document error:(NSError *)error;

快速集成代码

//
//  DocumentDemoViewController.m
//  VHYunSDKDemo
//
//  Created by vhall on 2018/10/15.
//  Copyright © 2018年 www.vhall.com. All rights reserved.
//

#import "DocumentDemoViewController.h"
#import "VHDocument.h"


#define OBJ_Color @[@"#FF0000",@"#FF7D00",@"#FFFF00",@"#00FF00",@"#0000FF",@"#00FFFF",@"#FF00FF",@"#000000"]

@interface DocumentDemoViewController ()<VHDocumentDelegate>
{
    UIColor   *_color;
    NSInteger _size;
}
@property(nonatomic,strong)VHDocument * document;
@property (weak, nonatomic) IBOutlet UIView *preView;
@property (weak, nonatomic) IBOutlet UILabel *infoLabel;
@property (weak, nonatomic) IBOutlet UIView *pptOptView;
@property (weak, nonatomic) IBOutlet UITextField *docIDTextField;

@property (weak, nonatomic) IBOutlet UILabel *lineSizeLabel;
@end

@implementation DocumentDemoViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view from its nib.
    //阻止iOS设备锁屏
    [[UIApplication sharedApplication] setIdleTimerDisabled: YES];
    _size = 5;
    [self initView];
}

- (void)dealloc
{
    //允许iOS设备锁屏
    [[UIApplication sharedApplication] setIdleTimerDisabled:NO];
}
/*
#pragma mark - Navigation

// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
    // Get the new view controller using [segue destinationViewController].
    // Pass the selected object to the new view controller.
}
*/
- (void)initView
{
    _document = [[VHDocument alloc]initWithChannelID:self.channelID accessToken:self.accessToken];
    _document.delegate = self;
    _document.view.frame = _preView.bounds;
    _document.view.backgroundColor = MakeColorRGB(0xE2E8EB);
    [_preView addSubview:_document.view];
    
    _document.view.editEnable = _isPublish;
    _pptOptView.hidden = !_isPublish;
}

- (void)viewDidLayoutSubviews
{
    _document.view.frame    = _preView.bounds;
}

- (IBAction)backBtnClicked:(id)sender {
    [self dismissViewControllerAnimated:YES completion:^{
    }];
    [self.navigationController popViewControllerAnimated:NO];
}

- (IBAction)pptShowOptBtnClicked:(UIButton *)sender
{
    sender.selected = !sender.selected;
    _document.view.editEnable = sender.selected;
    _pptOptView.hidden = !sender.selected;
}

- (IBAction)pptOptBtnClicked:(UIButton*)sender {
    switch (sender.tag) {
        case 100://上一页
            [_document.view prevPage];
            break;
        case 101://上一步
            [_document.view prevStep];
            break;
        case 102://下一步
            [_document.view nextStep];
            break;
        case 103://下一页
            [_document.view nextPage];
            break;
        default:
            break;
    }
}

- (IBAction)setDocBtnClicked:(id)sender {
    __weak typeof(self) wf = self;
    [_document setDocWithID:_docIDTextField.text];
}


- (IBAction)btnClicked:(UIButton*)sender {
    for (int i = 1; i <= 10; i++) {
        UIButton*v = [_pptOptView viewWithTag:i];
        if([v isKindOfClass:[UIButton class]])
        {
            v.selected = NO;
        }
    }
    
    if(!_document.view.editGraffitEnable)
        return;
    
    sender.selected = NO;
    switch (sender.tag) {
        case VHDrawType_Pen:
        case VHDrawType_Highlighter:
        case VHDrawType_Rectangle:
        case VHDrawType_Circle:
        case VHDrawType_Arrow:
        {
            sender.selected = YES;
            _document.view.drawType = sender.tag;
            [_document.view setColor:_color];
            [_document.view setSize:_size];
        }
            break;
        case VHDrawType_Text:
        {
            sender.selected = YES;
            _document.view.drawType = sender.tag;
        }
            break;
        case VHDrawType_Image:
        {

        }
            break;
        case 10://选择修改模式
        {
            sender.selected = YES;
            _document.view.drawAction = VHDrawAction_Modify;
        }
            break;
        case 11:_document.view.drawAction = VHDrawAction_Delete; break;//Del
        case 12:[_document.view clear];break;//DelAll
        case 13:[_document.view undo];break;//Undo
        case 14:[_document.view redo];break;//Redo
        default:break;
    }
}
- (IBAction)sliderValueChanged:(UISlider *)sender {
    switch (sender.tag) {
        case 90:
        {
            _size = sender.value;
            [_document.view setSize:_size];
            _lineSizeLabel.text = [NSString stringWithFormat:@"线/字大小:%d",(int)_size];
        }
            break;
        default:
            break;
    }
}
- (IBAction)colorValueChanged:(UISegmentedControl *)sender {
    NSString *colorStr = OBJ_Color[sender.selectedSegmentIndex];
    _color = [DocumentDemoViewController CGColor:colorStr];
    [_document.view setColor:_color];
}

- (IBAction)editGraffitEnablebtnClicked:(UIButton*)sender {
    sender.selected = !sender.selected;
    _document.view.editGraffitEnable = sender.selected;
    if(_document.view.editGraffitEnable)
        [self btnClicked:nil];
}

 #pragma mark - VHDocumentDelegate
- (void)documentViewDidLoad
{

}
- (void)document:(VHDocument *)document documentID:(NSString*) documentID curPage:(int)curPage
{
    _docIDTextField.text = documentID;
    _infoLabel.text = [NSString stringWithFormat:@"Page: %d/%d  Step:%d/%d",_document.view.currentPage+1,_document.view.totalPage,_document.view.currentStep+1,_document.view.totalStep];
}

- (void)document:(VHDocument *)document error:(NSError *)error
{
    [self showMsg:error.domain afterDelay:2];
}

- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
    [textField resignFirstResponder];
    return YES;
}

#pragma mark -
+ (UIColor*)CGColor:(NSString*)str
{
    NSRange r = [str rangeOfString:@"#"];
    if(r.location != NSNotFound)
        str = [str stringByReplacingOccurrencesOfString:@"#" withString:@"0x"];
    
    r = [str rangeOfString:@"0x"];
    if(r.location == NSNotFound)
        return [UIColor clearColor];
    
    unsigned long c = strtoul([str UTF8String],0,16);
    return [UIColor colorWithRed: ((c>>16)&0xFF) / 255.0  green: ((c>>8)&0xFF) / 255.0  blue: (c&0xFF) / 255.0  alpha: 1 ];
}

@end

其他相关文档

  1. 快速开始
  2. 文档模块参考手册