iOS音视频会议开发说明
1、网络会议开发说明
1.1 接口逻辑
接口调用是采取“请求回调”和“通知回调”的方式和服务端交互。用户发出邀请、踢出、解散等操作时,在对应的sdk的方法参数中有“请求回调”方法,请求的结果直接在参数的回调方法中处理。会议中的成员收到服务端发送过来的消息通过“通知回调”方法-(void)onReceivedConferenceNotification:(ECConferenceNotification*)info;来接收并进行处理。
1.2 业务流程
(1)用户A创建会议,本地无会议室id,通过sdk方法查询会议室id得到并创建。
(2)用户A邀请用户B,用户B收到通知 用户B设置入会状态 加入会议。
(3)用户A可以对所有会议成员静音、踢出等操作。
(4)用户A为主持人可解散会议,其他成员只能退出会议。
1.3 常见业务流程示意图
1.3.1 创建会议
1.3.2 加入会议
1.3.3 禁言成员
1.3.4 关闭成员视频
2、会议操作代码示例
2.1 创建会议
- ECConferenceMemberInfo *myMemberInfo = [[ECConferenceMemberInfo alloc] init];
- ECAccountInfo *accountInfo = [[ECAccountInfo alloc] init];
- //账号Id
- accountInfo.accountId = account;
- //昵称
- accountInfo.userName = name;
- account.accountType = ECAccountType_AppNumber;
- myMemberInfo.account = accountInfo;
- ECConferenceInfo *conferenceInfo = [ECConferenceInfo new];
- //会议名称
- conferenceInfo.confName = conferencename;
- //最大成员数
- conferenceInfo.maxMember = kConfMaxSquare;
- //背景提示音
- conferenceInfo.voiceMode = ECConferenceVoiceMode_All;
- //多路视频流
- conferenceInfo.mediaType = ECConferenceMediaType_MultiVideo;
- //到时间之后是否发送入会邀请(对于应用账号发送邀请通知,对于手机号发起邀请呼叫) 0:否,1:是 默认值 1
- conferenceInfo.sendInvitation = 1;
- //是否启用预约功能 0:不启用,1:启用
- conferenceInfo.reserveEnable = 0;
- //预约的会议中使用这个字段,会议开始前多久发送提醒通知。单位:分钟 默认值10
- conferenceInfo.remindBeforeStart = 3;
- //主持人离开会议后,会议是否自动结束 (0:否,1:是)
- conferenceInfo.autoClose = 0;
- //会议类型
- conferenceInfo.confType = ECConferenceType_Temporary;
- //会议成员数组
- conferenceInfo.members =@[myMemberInfo];
- conferenceInfo.appData = nil;
- //会议id
- conferenceInfo.conferenceRoomId = roomId;
- NSDate *date = [NSDate date];
- NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
- [formatter setDateStyle:NSDateFormatterMediumStyle];
- [formatter setTimeStyle:NSDateFormatterShortStyle];
- [formatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
- //设置开始时间
- conferenceInfo.startTime = [formatter stringFromDate:date];
- NSUInteger state = 0;
- if (!mute) {
- state = state|UserStateAllowSpeak; /** 共享语音 */
- }
- if (!video) {
- state = state|UserStateCameraSharing;/** 共享视频 */
- }
- state = state|ECConferenceMemberState_Listen; /** 可听 */
- //成员入会时状态(是否打开语音或视频)
- conferenceInfo.joinState = state;
- [[ECDevice sharedInstance].conferenceManager createConference:conferenceInfo completion:^(ECError *error, ECConferenceInfo *conferenceInfo) {
- }];//得到会信息
2.2 会议中邀请其他成员加入会议
- 功能:邀请成员加入会议。
- 参数:newArr会议成员数组,数组存储ECAccountInfo类型对象;
- confId会议房间id。
- callImmediately是否立即发起呼叫 对于自定义账号,1表示给用户显示呼叫页面,并设置超时时间1分钟 对于电话号码(或关联电话)账号,1表示立即给cm发呼叫命令 0表示仅在会议中增加成员(一般用户预约会议开始前增加成员)
- [[ECDevice sharedInstance].conferenceManager inviteMembers:newArr inConference:_conferenceId callImmediately:1 appData:nil completion:^(ECError *error) {
- if (error.errorCode == ECErrorType_NoError) {
- [SVProgressHUD showSuccessWithStatus:@"邀请成功"];
- }else{
- [SVProgressHUD showErrorWithStatus:error.errorDescription?:@"邀请失败"];
- }
- }];
2.3 被邀请方加入会议:
- 1. 实现代理方法得到 ECConferenceInviteNotification 对象
- - (void)onReceivedConferenceNotification:(ECConferenceNotification*)info{
- int var = info.type;
- if (var==ECConferenceNotificationType_Invite) {
- ECConferenceInviteNotification *inviteInfoMsg = (ECConferenceInviteNotification*)info;
- }
- }
- 2. 加入会议
- ECConferenceJoinInfo *joinInfo = [ECConferenceJoinInfo new]//会议加入信息;
- joinInfo.conferenceId = inviteInfoMsg.conferenceId;//会议id
- joinInfo.userName = _nickName;//用户昵称
- joinInfo.mediaType = ECConferenceMediaType_MultiVideo;
- NSUInteger state = 0;
- if (!_mute) {
- state = state|UserStateAllowSpeak;
- }
- if (!_closeVideo) {
- state = state|UserStateCameraSharing;
- }
- state = state|ECConferenceMemberState_Listen;
- joinInfo.joinState = state;
- joinInfo.terminalUA = @"iPhone";
- WS(weakSelf)
- [[ECDevice sharedInstance].conferenceManager joinConferenceWith:joinInfo completion:^(ECError *error, ECConferenceInfo *conferenceInfo) {
- if (error.errorCode == ECErrorType_NoError) {
- //根据后台返回的实际状态来发布音视频
- weakSelf.mute = !(conferenceInfo.joinStateAfterJoin&UserStateAllowSpeak);//是否静音
- weakSelf.closeVideo = !(conferenceInfo.joinStateAfterJoin&UserStateCameraSharing);是否关闭视频
- if ((!(conferenceInfo.joinState&UserStateAllowSpeak)) &&
- (!(conferenceInfo.joinState&UserStateCameraSharing))) {
- NSLog(@"主持人已禁止音视频");
- }else if (!(conferenceInfo.joinState&UserStateAllowSpeak)) {
- NSlog(@"主持人已禁止音频");
- }else if (!(conferenceInfo.joinState&UserStateCameraSharing)) {
- NSlog(@"主持人已禁止视频");
- }
- if (!weakSelf.mute) {
- //用户发布音频
- [[ECDevice sharedInstance].conferenceManager publishVoiceInConference:conferenceInfo.conferenceId completion:^(ECError *error) {
- if (error.errorCode == ECErrorType_NoError) {
- weakSelf.muteBtn.selected = NO;
- weakSelf.muteLabel.text = @"静音";
- } else {
- }
- }];
- }
- if (!weakSelf.closeVideo) {
- //用户发布视频
- [[ECDevice sharedInstance].conferenceManager publishVideoInConference:conferenceInfo.conferenceId completion:^(ECError *error) {
- if (error.errorCode == ECErrorType_NoError) {
- } else {
- }
- }];
- }
- }
- else {
- if (error.errorCode == ECErrorType_NotExist||
- error.errorCode == 814006) {
- error.errorDescription = [NSString stringWithFormat: @"会议已不存在!"];
- }else if (error.errorCode == 814011){
- error.errorDescription = [NSString stringWithFormat: @"会议室成员已达上限"];
- }else if (error.errorCode == 814012){
- error.errorDescription = [NSString stringWithFormat: @"当前会议禁止其他人进入"];
- }
- [SVProgressHUD showErrorWithStatus:error.errorDescription?:@"加入会议失败"];
- }
- }];
2.4 被邀请方拒绝加入会议
- 1 实现代理方法得到 ECConferenceInviteNotification 对象
- - (void)onReceivedConferenceNotification:(ECConferenceNotification*)info{
- int var = info.type;// 通知类型
- if (var==ECConferenceNotificationType_Invite) {
- ECConferenceInviteNotification *inviteInfoMsg = (ECConferenceInviteNotification*)info;
- }
- }
- 2.调用sdk 拒绝加入会议方法
- [[ECDevice sharedInstance].conferenceManager rejectInvitation:@"" cause:@"" ofConference:inviteInfoMsg.conferenceId completion:^(ECError *error) {
- if (error.errorCode == ECErrorType_NoError) {
- }
- }];
2.5 会议成员退出会议
- 功能:成员退出会议。
- 参数:conferenceId会议id
- 返回值:无
- NSString* conferenceId = @“会议ID”
- [[ECDevice sharedInstance].conferenceManager quitConference:conferenceId completion:^(ECError *error) {
- [SVProgressHUD dismiss];
- if (error.errorCode == ECErrorType_NoError) {
- NSlog(@"退出会议成功");
- }else{
- NSlog(@"退出会议失败");
- }
- }];
2.6 主动加入会议
- 功能:用户主动某一个加入会议。
- 参数:conferenceId 会议id
- nickname 用户名;
- ECConferenceJoinInfo *joinInfo = [ECConferenceJoinInfo new]//会议加入信息;
- joinInfo.conferenceId = conferenceId;//会议id
- joinInfo.userName = nickname;//用户昵称
- joinInfo.mediaType = ECConferenceMediaType_MultiVideo;
- NSUInteger state = 0;
- if (!_mute) {
- state = state|UserStateAllowSpeak;
- }
- if (!_closeVideo) {
- state = state|UserStateCameraSharing;
- }
- state = state|ECConferenceMemberState_Listen;
- joinInfo.joinState = state;
- joinInfo.terminalUA = @"iPhone";
- WS(weakSelf)
- [[ECDevice sharedInstance].conferenceManager joinConferenceWith:joinInfo completion:^(ECError *error, ECConferenceInfo *conferenceInfo) {
- if (error.errorCode == ECErrorType_NoError) {
- //根据后台返回的实际状态来发布音视频
- weakSelf.mute = !(conferenceInfo.joinStateAfterJoin&UserStateAllowSpeak);//是否静音
- weakSelf.closeVideo = !(conferenceInfo.joinStateAfterJoin&UserStateCameraSharing);是否关闭视频
- if ((!(conferenceInfo.joinState&UserStateAllowSpeak)) &&
- (!(conferenceInfo.joinState&UserStateCameraSharing))) {
- NSLog(@"主持人已禁止音视频");
- }else if (!(conferenceInfo.joinState&UserStateAllowSpeak)) {
- NSlog(@"主持人已禁止音频");
- }else if (!(conferenceInfo.joinState&UserStateCameraSharing)) {
- NSlog(@"主持人已禁止视频");
- }
- if (!weakSelf.mute) {
- //用户发布音频
- [[ECDevice sharedInstance].conferenceManager publishVoiceInConference:conferenceInfo.conferenceId completion:^(ECError *error) {
- if (error.errorCode == ECErrorType_NoError) {
- weakSelf.muteBtn.selected = NO;
- weakSelf.muteLabel.text = @"静音";
- } else {
- }
- }];
- }
- if (!weakSelf.closeVideo) {
- //用户发布视频
- [[ECDevice sharedInstance].conferenceManager publishVideoInConference:conferenceInfo.conferenceId completion:^(ECError *error) {
- if (error.errorCode == ECErrorType_NoError) {
- } else {
- }
- }];
- }
- }
- else {
- if (error.errorCode == ECErrorType_NotExist||
- error.errorCode == 814006) {
- error.errorDescription = [NSString stringWithFormat: @"会议已不存在!"];
- }else if (error.errorCode == 814011){
- error.errorDescription = [NSString stringWithFormat: @"会议室成员已达上限"];
- }else if (error.errorCode == 814012){
- error.errorDescription = [NSString stringWithFormat: @"当前会议禁止其他人进入"];
- }
- [SVProgressHUD showErrorWithStatus:error.errorDescription?:@"加入会议失败"];
- }
- }];
2.7 解散会议
解散视频会议我们假设Tony要解散自己创建的一个会议
- 功能:只有创建者能解散会议 其他会议成员无权限。
- 参数:conferenceId会议id
- 返回值:无
- [[ECDevice sharedInstance].conferenceManager deleteConference: conferenceId completion:^(ECError *error) {
- if (error.errorCode == ECErrorType_NoError) {
- NSlog(@"解散会议成功");
- }else{
- NSlog(@"解散会议失败");
- }
- }];
2.8 预约会议
- 1.先本地获取会议室ID,本地无调用sdk查询会议室ID
- //生成账号信息对象
- ECAccountInfo *account = [[ECAccountInfo alloc] init];
- //用户id
- account.accountId = userId;
- //账号类型
- account.accountType = memberType;
- //会议室ID
- __block NSString *roomId = @"";
- [[ECDevice sharedInstance].conferenceManager getConfroomIdListWithAccount:account confId:nil completion:^(ECError *error, NSArray *arr) {
- if (arr && arr.count>0) {
- for (int i = 0; i<arr.count; i++) {
- ECConferenceRoomInfo *info = arr[i];
- if ([info.member.accountId isEqualToString:userId] &&
- info.member.accountType == ECAccountType_AppNumber) {
- if (info.confRoomId) {
- roomId = info.confRoomId;
- }
- }
- }
- }
- }];
- 2. 创建预约会议
- ECConferenceMemberInfo *myMemberInfo = [[ECConferenceMemberInfo alloc] init];
- ECAccountInfo *accountInfo = [[ECAccountInfo alloc] init];
- //账号Id
- accountInfo.accountId = account;
- //昵称
- accountInfo.userName = name;
- account.accountType = ECAccountType_AppNumber;
- myMemberInfo.account = accountInfo;
- ECConferenceInfo *conferenceInfo = [ECConferenceInfo new];
- //会议名称
- conferenceInfo.confName = conferencename;
- //最大人数
- conferenceInfo.maxMember = kConfMaxSquare;
- //背景提示音
- conferenceInfo.voiceMode = ECConferenceVoiceMode_All;
- //多路视频流
- conferenceInfo.mediaType = ECConferenceMediaType_MultiVideo;
- //会议开始时间
- conferenceInfo.startTime = startTime;
- //会议持续时间(15分钟的多少倍
- conferenceInfo.duration = duration*15;
- ;//到时间之后是否发送入会邀请(对于应用账号发送邀请通知,对于手机号发起邀请呼叫) 0:否,1:是 默认值 1
- conferenceInfo.sendInvitation = 1
- //是否启用预约功能 0:不启用,1:启用
- conferenceInfo.reserveEnable = 1;
- //预约的会议中使用这个字段,会议开始前多久发送提醒通知。单位:分钟 默认值10
- conferenceInfo.remindBeforeStart = 3;
- //主持人离开会议后,会议是否自动结束 (0:否,1:是)
- conferenceInfo.autoClose = 0;
- //会议类型
- conferenceInfo.confType = ECConferenceType_Temporary;
- conferenceInfo.members = @[myMemberInfo];
- //会议室ID
- conferenceInfo.conferenceRoomId = roomId;
- NSUInteger state = 0;
- if (!mute) {
- state = state|UserStateAllowSpeak;
- }
- if (!video) {
- state = state|UserStateCameraSharing;
- }
- state = state|ECConferenceMemberState_Listen;
- conferenceInfo.joinState = state;
- [[ECDevice sharedInstance].conferenceManager createConference:conferenceInfo completion:^(ECError *error, ECConferenceInfo *conferenceInfo) {
- if (completion != nil) {
- }
- }];
2.9 更新预约会议
- ECConferenceInfo *conferenceInfo = [ECConferenceInfo new];
- conferenceInfo.conferenceId = conferenceId;
- conferenceInfo.confName = conferencename;
- conferenceInfo.maxMember = kConfMaxSquare;
- conferenceInfo.voiceMode = ECConferenceVoiceMode_All;
- conferenceInfo.mediaType = ECConferenceMediaType_MultiVideo;
- conferenceInfo.startTime = startTime;
- conferenceInfo.duration = (duration>=0)?(duration*15):duration;
- conferenceInfo.sendInvitation = 1;
- conferenceInfo.reserveEnable = 1;
- conferenceInfo.autoClose = 0;
- conferenceInfo.confType = ECConferenceType_Temporary;
- conferenceInfo.members = meetingMember;
- conferenceInfo.confTopic = TopicStr;
- if (mute>=0 && video>=0) {
- NSUInteger state = 0;
- if (!mute) {
- state = state|UserStateAllowSpeak;
- }
- if (!video) {
- state = state|UserStateCameraSharing;
- }
- state = state|ECConferenceMemberState_Listen;
- conferenceInfo.joinState = state;
- }else{
- conferenceInfo.joinState = -1;
- }
- [[ECDevice sharedInstance].conferenceManager updateConference:conferenceInfo completion:^(ECError *error
- }];
3.0 踢出成员
- 功能:从会议移除成员
- 参数:
- kickMembers ECAccountInfo数组 踢出的成员
- confId 会议ID。
- appData 预留
- 返回值:无.
- NSMutableArray *deleArr;
- NSString *confId = @"会议id";
- [[ECDevice sharedInstance].conferenceManager kickMembers:deleArr outConference:confId appData:nil completion:^(ECError *error) {
- if (error.errorCode == ECErrorType_NoError) {
- [SVProgressHUD showSuccessWithStatus:@"删除完成"];
- }else{
- [SVProgressHUD showErrorWithStatus:error.errorDescription?:@"删除失败"];
- }
- }];
3.1 会议媒体控制
成员的静音,解除静音,停止发布视频等。
- 功能:创建者对成员静音,解除静音,关闭其视频,开启视频等。
- 参数:ECControlMediaAction 控制动作 枚举
- members ECAccountInfo数组 控制成员列表
- isAllMember 是否全部成员
- confId 会议ID
- 返回值:无
- [[ECDevice sharedInstance].conferenceManager controlMedia:ECControlMediaAction_CloseSpeak toMembers:@[] isAll:NO ofConference:self.conferenceId completion:^(ECError *error) {
- if (error.errorCode == ECErrorType_NoError) {
- [SVProgressHUD showSuccessWithStatus:@"静音成功"];
- } else {
- if(error.errorCode ==171139) {
- [SVProgressHUD showErrorWithStatus:@"请求服务器失败,请检查网络状况"];
- return;
- }
- [SVProgressHUD showErrorWithStatus:@"静音失败"];
- }
- }]
3.2 查询当前会议成员
用户加入会议后,需要获取当前会议中的所有成员
- 功能:查询会议中的成员列表。
- 参数: confId 会议ID
- page 分页信息
- [[ECDevice sharedInstance].conferenceManager getMemberListOfConference:confId page:page completion:^(ECError *error, NSArray *memberInfos) {
- if(error.errorCode == ECErrorType_NoError) {
- }
- else if (error.errorCode == ECErrorType_NotExist||
- error.errorCode == 814006){
- [SVProgressHUD showErrorWithStatus:error.errorDescription?:@"会议不存在"];
- }
- else {
- [SVProgressHUD showErrorWithStatus:@"获取成员失败"];
- }
- }];
3.3 会议取消发布自己的视频
用户想关闭自己的视频(可以看到会议室中其他成员视频
- NSString* confid =@”当前的会议id”;
- [[ECDevice sharedInstance].conferenceManager cancelVideoInConference:confid completion:^(ECError *error) {
- weakBtn.userInteractionEnabled = YES;
- if (error.errorCode == ECErrorType_NoError) {
- } else {
- [SVProgressHUD showErrorWithStatus:@"关闭摄像头失败"];
- }
- }];
3.4 会议发布自己的视频
用户关闭的视频重新打开自己视频。
- NSString* confid =@”当前的会议id”;
- [[ECDevice sharedInstance].conferenceManager publishVideoInConference:confid completion:^(ECError *error) {
- if (error.errorCode == ECErrorType_NoError) {
- } else {
- }
- }];
3.5 会议中用户想对自己的静音
- NSString* confid =@”当前的会议id”;
- [[ECDevice sharedInstance].conferenceManager stopVoiceInConference:confid completion:^(ECError *error) {
- weakBtn.userInteractionEnabled = YES;
- if (error.errorCode == ECErrorType_NoError) {
- } else {
- [SVProgressHUD showErrorWithStatus:@"静音失败"];
- }
- }];
3.6 会议中用户对自己解除静音
- NSString* confid =@”当前的会议id”;
- [[ECDevice sharedInstance].conferenceManager publishVoiceInConference: confid completion:^(ECError *error) {
- weakBtn.userInteractionEnabled = YES;
- if (error.errorCode == ECErrorType_NoError) {
- } else {
- [SVProgressHUD showErrorWithStatus:@"解除静音失败"];
- }
- }];
3.7 会议锁定
会议创建者锁定会议
- 功能:会议创建才有权限锁定,锁定会议后将不能有新的参会者加入会议。
- 参数: confId 会议ID
- lockType 0 锁定,1 解锁
- [[ECDevice sharedInstance].conferenceManager lockConference:confId lockType:0 completion:^(ECError *error) {
- }];
3.8 获取会议列表
- 功能:获取应用下会议列表。
- 参数: condition 筛选条件
- page 分页信息
- member 用户账号信息
- account 用户账号
- ECConferenceCondition *conditionInfo = [ECConferenceCondition new];
- conditionInfo.searchType = ECConferenceSearchType_All;
- conditionInfo.confType = -1
- ECAccountInfo *myMember = [ECAccountInfo new];
- member.accountId = account;
- member.accountType = ECAccountType_AppNumber;
- [[ECDevice sharedInstance].conferenceManager getConferenceListWithCondition:conditionInfo page:page ofMember: myMember completion:^(ECError *error, NSArray *conferenceList) {
- }];
3.9 获取历史会议列表
- 功能:获取历史会议列表。
- 参数: condition 筛选条件
- page 分页信息
- ECConferenceCondition *conditionInfo = [ECConferenceCondition new];
- conditionInfo.searchType = ECConferenceSearchType_All;
- conditionInfo.confType = -1;
- [[ECDevice sharedInstance].conferenceManager getHistoryCsonferenceListWithCondition:conditionInfo page:page completion:^(ECError *error, NSArray *conferenceList) {
- }];
3.10 会议通知消息
当对会议进行操作(如主动加入、退出、解散、踢出成员)时,会议室中的相关成员通过会议的“通知回调”接口onReceivedConferenceNotification接收相关信息,并进行处理,其代码示例如下
- - (void)onReceivedConferenceNotification:(ECConferenceNotification*)info {
- int var = info.type;
- if (var==ECConferenceNotificationType_Invite) {
- NSLog(@"会议邀请");
- }else if (var == ECConferenceNotificationType_Subscribe){
- NSLog(@"会议预约");
- }else if (var == ECConferenceNotificationType_Recommend) {
- NSLog(@"用户推荐通知");
- }else if (var == ECConferenceNotificationType_Update) {
- NSLog(@"会议信息更新");
- }else if (var == ECConferenceNotificationType_Near){
- NSLog(@"会议即将开始");
- }else if (var == ECConferenceNotificationType_Delete){
- NSLog(@"会议删除");
- }
- }
- }];
3.11 请求成员视频
- 功能:请求成员视频
- 参数: videoInfo 视频信息
- conferenceId // 会议id
- sourceType //视频源
- account //视频属于的用户
- view // 本地显示窗口
- ECConferenceVideoInfo *videoInfo = [[ECConferenceVideoInfo alloc] init];
- videoInfo.conferenceId = conferenceId;
- videoInfo.sourceType = ECConferenceSourceType_Video;
- videoInfo.member = account ;
- info.view = view ;
- [[ECDevice sharedInstance].conferenceManager requestMemberVideoWith:videoInfo completion:^(ECError *error) {
- }];]
3.12 停止成员视频
- 功能:请求成员视频
- 参数: videoInfo 视频信息
- conferenceId // 会议id
- sourceType //视频源
- account //视频属于的用户
- view // 本地显示窗口
- ECConferenceVideoInfo *videoInfo = [[ECConferenceVideoInfo alloc] init];
- videoInfo.conferenceId = onferenceId;
- videoInfo.sourceType = ECConferenceSourceType_Video;
- videoInfo.member = account;
- videoInfo.view = nil;
- [[ECDevice sharedInstance].conferenceManager stopMemberVideoWith:videoInfo completion:^(ECError *error) {
- }];
3.13 重置显示View
- 功能:重置显示view
- 参数: videoInfo 视频信息
- conferenceId // 会议id
- sourceType //视频源
- account //视频属于的用户
- view // 本地显示窗口
- [[ECDevice sharedInstance].conferenceManager resetMemberVideoWith:videoInfo];
3.14 重置本地预览显示View
- 功能:重置本地预览View
- 参数: conferenceId // 会议id
- view // 本地view
- [[ECDevice sharedInstance].conferenceManager resetLocalVideoWithConfId:self.conferenceId remoteView:nil localView:view];