Overview of Scenario-Based Solutions
소셜 엔터테인먼트
이커머스 라이브 방송
Audio/Video Call
원거리 실시간 조작
스마트 고객 서비스
AI 인터뷰





sudo gem install cocoapods
pod init
platform :ios, '8.0'target 'App' do# RTC Engine 라이트 버전# 설치 패키지의 크기 증가가 최소화되어 있어서 RTC Engine 및 라이브방송 플레이어(TXLivePlayer) 두 가지 기능만 지원됩니다.pod 'TXLiteAVSDK_TRTC', :podspec => 'https://liteav.sdk.qcloud.com/pod/liteavsdkspec/TXLiteAVSDK_TRTC.podspec’# Add the Chat SDKpod 'TXIMSDK_Plus_iOS'# pod 'TXIMSDK_Plus_iOS_XCFramework'# pod 'TXIMSDK_Plus_Swift_iOS_XCFramework'# If you need to add the Quic plugin, please uncomment the next line.# Note: This plugin must be used with the Objective-C edition or XCFramework edition of the Chat SDK, and the plugin version number must match the Chat SDK version number.# pod 'TXIMSDK_Plus_QuicPlugin'end
pod install
pod update
pod setuppod repo updaterm ~/Library/Caches/CocoaPods/search_index.json
Privacy - Microphone Usage Description,마이크 사용 목적 안내문을 함께 입력하세요



// Chat IM 콘솔에서 애플리케이션 SDKAppID를 획득합니다.// V2TIMSDKListener의 이벤트 리스너를 추가합니다. self는 id<V2TIMSDKListener>의 구현 클래스이고 Chat SDK의 이벤트를 감지할 필요가 없는 경우 이 단계는 생략할 수 있습니다.[[V2TIMManager sharedInstance] addIMSDKListener:self];// Chat SDK를 초기화합니다. 이 인터페이스를 호출한 후 즉시 로그인 인터페이스를 호출할 수 있습니다.[[V2TIMManager sharedInstance] initSDK:sdkAppID config:config];// SDK 초기화 후 연결 상태, 로그인 티켓 만료 등 일부 이벤트가 발생할 수 있습니다- (void)onConnecting {NSLog(@"Chat SDK가 텐센트 클라우드 서버에 연결 중입니다");}- (void)onConnectSuccess {NSLog(@"Chat SDK가 텐센트 클라우드 서버에 성공적으로 연결되었습니다");}// 이벤트 리스너의 제거// self는 id<V2TIMSDKListener>의 구현 클래스입니다[[V2TIMManager sharedInstance] removeIMSDKListener:self];// SDK 초기화의 해제[[V2TIMManager sharedInstance] unInitSDK];
// RTC Engine SDK 인스턴스의 생성(싱글톤 모드)_trtcCloud = [TRTCCloud sharedInstance];// 이벤트 리스너의 설정_trtcCloud.delegate = self;// SDK의 다양한 이벤트 알림(예: 오류 코드, 경고 코드, 오디오/비디오 상태 매개변수 등)- (void)onError:(TXLiteAVError)errCode errMsg:(nullable NSString *)errMsg extInfo:(nullable NSDictionary *)extInfo {NSLog(@"%d: %@", errCode, errMsg);}- (void)onWarning:(TXLiteAVWarning)warningCode warningMsg:(nullable NSString *)warningMsg extInfo:(nullable NSDictionary *)extInfo {NSLog(@"%d: %@", warningCode, warningMsg);}// 이벤트 리스너의 제거_trtcCloud.delegate = nil;// RTC Engine SDK 인스턴스(싱글톤 모드)를 파기합니다.[TRTCCloud destroySharedIntance];
// 로그인: userID는 사용자 자체 정의 가능하고 userSig는 단계1 참조하여 생성 및 획득합니다[[V2TIMManager sharedInstance] login:userID userSig:userSig succ:^{NSLog(@"success");} fail:^(int code, NSString *desc) {// 다음 오류 코드가 반환되면 UserSig가 만료되었음을 의미하므로 새로 발급된 UserSig를 사용하여 다시 로그인하십시오.// 1. ERR_USER_SIG_EXPIRED(6206)// 2. ERR_SVR_ACCOUNT_USERSIG_EXPIRED(70001)// 주의: 다른 오류 코드의 경우 여기에서 로그인 인터페이스를 호출하지 마십시오. Chat SDK 로그인이 무한 루프에 빠지는 것을 방지하기 위한 것입니다.NSLog(@"failure, code:%d, desc:%@", code, desc);}];
// 로그아웃[[V2TIMManager sharedInstance] logout:^{NSLog(@"success");} fail:^(int code, NSString *desc) {NSLog(@"failure, code:%d, desc:%@", code, desc);}];
// 그룹 생성[[V2TIMManager sharedInstance] createGroup:GroupType_AVChatRoom groupID:groupID groupName:groupName succ:^(NSString *groupID) {// 그룹 생성 성공} fail:^(int code, NSString *desc) {// 그룹 생성 실패}];// 그룹 생성 알림을 감시합니다[[V2TIMManager sharedInstance] addGroupListener:self];- (void)onGroupCreated:(NSString *)groupID {// 그룹 생성 콜백하고 groupID는 새로 생성된 그룹의 ID입니다}
GroupType_AVChatRoom.// 그룹 입장[[V2TIMManager sharedInstance] joinGroup:groupID msg:message succ:^{// 그룹 가입 성공} fail:^(int code, NSString *desc) {// 그룹 가입 실패}];// 그룹 가입 이벤트의 감시[[V2TIMManager sharedInstance] addGroupListener:self];- (void)onMemberEnter:(NSString *)groupID memberList:(NSArray<V2TIMGroupMemberInfo *>*)memberList {// 누군가 그룹에 가입했습니다}
- (void)enterRoomWithRoomId:(NSString *)roomId userID:(NSString *)userId {TRTCParams *params = [[TRTCParams alloc] init];// 문자열 방 번호를 예로 들면 IM 그룹 번호와 일치하는 것이 좋습니다params.strRoomId = roomId;params.userId = userId;// 업무 백엔드에서 가져온 UserSigparams.userSig = getUserSig(userId);// 손임의 SDKAppID로 교체합니다params.sdkAppId = SDKAppID;// 음성 채팅 상호 작용 시나리오에서 방에 들어가려면 사용자 역할을 지정해야 합니다params.role = TRTCRoleAudience;// 음성 채팅 인터랙티브 방 입장 시나리오를 예로 들어,[self.trtcCloud enterRoom:params appScene:TRTCAppSceneVoiceChatRoom];}// 방 입장 결과 이벤트의 콜백- (void)onEnterRoom:(NSInteger)result {if (result > 0) {// result는 방에 임장하는 데 소요된 시간(밀리초)을 나타냅니다.[self toastTip:@"Enter room succeed!"];} else {// result는 방 입장 실패의 오류 코드를 나타냅니다.[self toastTip:@"Enter room failed!"];}}
roomId와 문자열 형식 strRoomId로 나뉘며 두 유형의 방은 서로 통하지 않으므로 방 번호 유형을 통일하는 것을 권장합니다.TRTCAppSceneVoiceChatRoom을 사용하는 것이 좋습니다. [[V2TIMManager sharedInstance] quitGroup:groupID succ:^{// 그룹 나가기 성공} fail:^(int code, NSString *desc) {// 그룹 나가기 실패}];[[V2TIMManager sharedInstance] addGroupListener:self];- (void)onMemberLeave:(NSString *)groupID member:(V2TIMGroupMemberInfo *)member {// 그룹 멤버 나가기의 콜백}
dismissGroup을 호출하여 그룹을 해산할 수만 있습니다.- (void)exitTrtcRoom {self.trtcCloud = [TRTCCloud sharedInstance];[self.trtcCloud stopLocalAudio];[self.trtcCloud exitRoom];}// onExitRoom 콜백을 수신하여 자신의 퇴장 사유를 확인할 수 있습니다.- (void)onExitRoom:(NSInteger)reason {if (reason == 0) {// exitRoom을 호출하여 방에서 나가기.NSLog(@"Exit current room by calling the 'exitRoom' api of sdk ...");} else if (reason == 1) {//서버에 의해 현재 방에서 나가게 됩니다NSLog(@"Kicked out of the current room by server through the restful api...");} else if (reason == 2) {// 현재 방 전체가 해체됩니다NSLog(@"Current room is dissolved by server through the restful api...");}}
onExitRoom 콜백을 통해 알려줍니다.enterRoom을 다시 호출하거나 다른 음성/영상 SDK로 전환하려면 onExitRoom 콜백이 발생한 후 관련 작업을 수행하십시오. 그렇지 않으면 카메라, 마이크등 장치의 점유됨과 같은 다양한 이상 현상이 발생할 수 있습니다.[[V2TIMManager sharedInstance] dismissGroup:groupID succ:^{// 그룹 해산 성공} fail:^(int code, NSString *desc) {// 그룹 해산 실패}];[[V2TIMManager sharedInstance] addGroupListener:self];- (void)onGroupDismissed:(NSString *)groupID opUser:(V2TIMGroupMemberInfo *)opUser {// 그룹 해산 콜백}
DismissRoom(숫자 방 ID와 문자열 방 ID 구분)를 제공합니다. 이 인터페이스를 호출하여 방의 모든 사용자를 방에서 제거하고 방을 해산할 수 있습니다.exitRoom 인터페이스를 통해 방 내의 모든 스트리머와 청취자를 방에서 완전히 나가게 할 수 있습니다. 방을 나간 후, RTC Engine 방의 생명주기 규칙에 따라 방은 자동으로 해산됩니다. 자세한 내용은 방 나가기를 참조하세요.#import "JSONModel.h"typedef NS_ENUM(NSUInteger, SeatInfoStatus) {SeatInfoStatusUnused = 0,SeatInfoStatusUsed = 1,SeatInfoStatusLocked = 2,};NS_ASSUME_NONNULL_BEGIN@interface SeatInfoModel : JSONModel/// 좌석 상태는 세 가지 상태에 대응합니다@property (nonatomic, assign) SeatInfoStatus status;/// 죄석 금언 여부@property (nonatomic, assign) BOOL mute;/// 좌석이 점유됐을 때, 사용자 정보 저장합니다@property (nonatomic, copy) NSString *userId;@endNS_ASSUME_NONNULL_END
// 청취자가 마이크 요청을 보내며 userId는 스트리머 Id이고 data는 시그널링 식별을 위한 json을 전달할 수 있습니다- (void)sendInvitationWithUserId:(NSString *)userId data:(NSString *)data {[[V2TIMManager sharedInstance] invite:userId data:data onlineUserOnly:YES offlinePushInfo:nil timeout:0 succ:^{NSLog(@"sendInvitation success");} fail:^(int code, NSString *desc) {NSLog(@"sendInvitation error %d", code);}];}// 스트리머가 마이크 사용의 요청을 수신하며 inviteID는 해당 요청 Id이고 inviter는 요청자 ID입니다[[V2TIMManager sharedInstance] addSignalingListener:self];- (void)onReceiveNewInvitation:(NSString *)inviteID inviter:(NSString *)inviter groupID:(NSString *)groupID inviteeList:(NSArray<NSString *> *)inviteeList data:(NSString * __nullable)data {NSLog(@"received invitation: %@ from %@", inviteID, inviter);}
// 마이크 사용의 요청을 동의합니다- (void)acceptInvitationWithInviteID:(NSString *)inviteID data:(NSString *)data {[[V2TIMManager sharedInstance] accept:inviteID data:data succ:^{NSLog(@"acceptInvitation success");} fail:^(int code, NSString *desc) {NSLog(@"acceptInvitation error %d", code);}];}// 마이크 사용의 요청 거절합니다- (void)rejectInvitationWithInviteID:(NSString *)inviteID data:(NSString *)data {[[V2TIMManager sharedInstance] reject:inviteID data:data succ:^{NSLog(@"rejectInvitation success");} fail:^(int code, NSString *desc) {NSLog(@"rejectInvitation error %d", code);}];}
// 로컬에 저장된 전체 마이크 순위 정보의 목록@property (nonatomic, copy) NSArray<SeatInfoModel *> *seatInfoArray;// 마이크 요청 동의의 콜백- (void)onInviteeAccepted:(NSString *)inviteID invitee:(NSString *)invitee data:(NSString * __nullable)data {NSLog(@"received accept invitation: %@ from %@", inviteID, invitee);NSInteger seatIndex = [self findSeatIndex:inviteID];[self takeSeatWithIndex:seatIndex];}// 청취자가 마이크를 켜서 사용하기 시작합니다- (void)takeSeatWithIndex:(NSInteger)seatIndex {// 마이크 순위 정보 인스턴스 생성하며 수정된 마이크 순위 정보를 저장합니다SeatInfoModel *localInfo = self.seatInfoArray[seatIndex];SeatInfoModel *seatInfo = [[SeatInfoModel alloc] init];seatInfo.status = SeatInfoStatusUsed;seatInfo.mute = localInfo.mute;seatInfo.userId = self.userId;// 마이크 순위 정보 객체를 JSON 형식으로 직렬화합니다NSString *jsonStr = seatInfo.toJSONString;NSDictionary *dict = @{ [NSString stringWithFormat:@"seat%ld", seatIndex]: jsonStr };// 그룹 속성을 설정하고 해당 그룹 속성이 이미 있으면 value 값을 업데이트하고, 없으면 해당 속성을 추가합니다.[[V2TIMManager sharedInstance] setGroupAttributes:self.groupId attributes:dict succ:^{// 그룹 속성의 수정이 성공되고 TRTC 역할의 전환 및 스트리밍 시작합니다[self.trtcCloud switchRole:TRTCRoleAnchor];[self.trtcCloud startLocalAudio:TRTCAudioQualityDefault];} fail:^(int code, NSString *desc) {// 그룹 속성의 수정이 실패되고 마이크 연결이 실패됩니다}];}
// 로컬에 저장된 전체 마이크 순위 정보의 목록@property (nonatomic, copy) NSArray<SeatInfoModel *> *seatInfoArray;// 스트리머 측에서 해당 인터페이스를 호출하여 그룹 속성에 저장된 마이크 순위 정보를 수정합니다.- (void)pickSeatWithUserId:(NSString *)userId seatIndex:(NSInteger)seatIndex {// 마이크 순위 정보 인스턴스 생성하며 수정된 마이크 순위 정보를 저장합니다SeatInfoModel *localInfo = self.seatInfoArray[seatIndex];SeatInfoModel *seatInfo = [[SeatInfoModel alloc] init];seatInfo.status = SeatInfoStatusUsed;seatInfo.mute = localInfo.mute;seatInfo.userId = self.userId;// 마이크 순위 정보 객체를 JSON 형식으로 직렬화합니다NSString *jsonStr = seatInfo.toJSONString;NSDictionary *dict = @{ [NSString stringWithFormat:@"seat%ld", seatIndex]: jsonStr };// 그룹 속성 설정합니다.해당 그룹 속성이 이미 있으면 value 값을 업데이트하고 없으면 해당 속성을 추가합니다[[V2TIMManager sharedInstance] setGroupAttributes:self.groupId attributes:dict succ:^{// 그룹 속성의 수정이 성공되고 onGroupAttributeChanged 콜백 트리거됩니다} fail:^(int code, NSString *desc) {// 그룹 속성의 수정이 실패되며 마이크 연결이 실패됩니다}];}// 청취자 측에서 그룹 속성 변경 콜백을 수신하여 자체 정보에 매칭 성공 후 스트리밍 시작합니다[[V2TIMManager sharedInstance] addGroupListener:self];- (void)onGroupAttributeChanged:(NSString *)groupID attributes:(NSMutableDictionary<NSString *,NSString *> *)attributes {// 로컬에 저장된 기존의 전체 마이크 순위 정보 리스트NSArray *oldSeatArray = self.seatInfoArray;// groupAttributeMap에서 파싱한 최신 전체 마이크 순위 정보 리스트NSArray *newSeatArray = [self getSeatListFromAttr:attributes seatSize:self.seatSize];// 전체 마이크 순위 정보 리스트를 순회하며 새/구 마이크 정보를 비교합니다.for (int i = 0; i < self.seatSize; i++) {SeatInfoModel *oldInfo = oldSeatArray[i];SeatInfoModel *newInfo = newSeatArray[i];if (oldInfo.status != newInfo.status && newInfo.status == SeatInfoStatusUsed) {if ([newInfo.userId isEqualToString:self.userId]) {// 자신의 정보에 매칭 성공 후, RTC Engine 역할 전환 및 스트리밍 시작합니다[self.trtcCloud switchRole:TRTCRoleAnchor];[self.trtcCloud startLocalAudio:TRTCAudioQualityDefault];} else {// 로컬 마이크 순위 목록을 업데이트하고 로컬 마이크 순위 뷰 렌더링합니다}}}}
// 로컬에 저장된 전체 마이크 순위 정보의 목록@property (nonatomic, copy) NSArray<SeatInfoModel *> *seatInfoArray;- (void)leaveSeatWithIndex:(NSInteger)seatIndex {// 마이크 순위 정보 인스턴스 생성하며 수정된 마이크 순위 정보를 저장합니다SeatInfoModel *localInfo = self.seatInfoArray[seatIndex];SeatInfoModel *seatInfo = [[SeatInfoModel alloc] init];seatInfo.status = SeatInfoStatusUnused;seatInfo.mute = localInfo.mute;seatInfo.userId = @"";// 마이크 순위 정보 객체를 JSON 형식으로 직렬화합니다NSString *jsonStr = seatInfo.toJSONString;NSDictionary *dict = @{ [NSString stringWithFormat:@"seat%ld", seatIndex]: jsonStr };// 그룹 속성 설정합니다.해당 그룹 속성이 이미 있으면 value 값을 업데이트하고 없으면 해당 속성을 추가합니다[[V2TIMManager sharedInstance] setGroupAttributes:self.groupId attributes:dict succ:^{// 그룹 속성의 수정이 성공되고 RTC Engine 역할 전환 및 스트리밍 중지합니다[self.trtcCloud switchRole:TRTCRoleAudience];[self.trtcCloud stopLocalAudio];} fail:^(int code, NSString *desc) {// 그룹 속성의 수정이 실패되고 마이크 끄기가 실패됩니다}];}
// 로컬에 저장된 전체 마이크 순위 정보의 목록@property (nonatomic, copy) NSArray<SeatInfoModel *> *seatInfoArray;// 스트리머 측에서 해당 인터페이스를 호출하여 그룹 속성에 저장된 마이크 순위 정보를 수정합니다.- (void)kickSeatWithIndex:(NSInteger)seatIndex {// 마이크 순위 정보 인스턴스 생성하며 수정된 마이크 순위 정보를 저장합니다SeatInfoModel *localInfo = self.seatInfoArray[seatIndex];SeatInfoModel *seatInfo = [[SeatInfoModel alloc] init];seatInfo.status = SeatInfoStatusUnused;seatInfo.mute = localInfo.mute;seatInfo.userId = @"";// 마이크 순위 정보 객체를 JSON 형식으로 직렬화합니다NSString *jsonStr = seatInfo.toJSONString;NSDictionary *dict = @{ [NSString stringWithFormat:@"seat%ld", seatIndex]: jsonStr };// 그룹 속성 설정합니다.해당 그룹 속성이 이미 있으면 value 값을 업데이트하고 없으면 해당 속성을 추가합니다[[V2TIMManager sharedInstance] setGroupAttributes:self.groupId attributes:dict succ:^{// 그룹 속성의 수정이 성공되고 onGroupAttributeChanged 콜백 트리거됩니다} fail:^(int code, NSString *desc) {// 그룹 속성의 수정이 실패되고 마이크 끄기 실패됩니다}];}// 연결된 청취자 측에서 그룹 속성 변경 콜백을 수신하여 자체 정보에 매칭 성공 후 스트리밍 중지합니다[[V2TIMManager sharedInstance] addGroupListener:self];- (void)onGroupAttributeChanged:(NSString *)groupID attributes:(NSMutableDictionary<NSString *,NSString *> *)attributes {// 로컬에 저장된 기존의 전체 마이크 순위 정보 리스트NSArray *oldSeatArray = self.seatInfoArray;// groupAttributeMap에서 파싱한 최신 전체 마이크 순위 정보 리스트NSArray *newSeatArray = [self getSeatListFromAttr:attributes seatSize:self.seatSize];// 전체 마이크 순위 정보 리스트를 순회하며 새/구 마이크 정보를 비교합니다.for (int i = 0; i < self.seatSize; i++) {SeatInfoModel *oldInfo = oldSeatArray[i];SeatInfoModel *newInfo = newSeatArray[i];if (oldInfo.status != newInfo.status && newInfo.status == SeatInfoStatusUnused) {if ([newInfo.userId isEqualToString:self.userId]) {// 자신의 정보에 매칭 성공 후 RTC Engine 역할을 전환하고 스트리밍을 중지합니다.[self.trtcCloud switchRole:TRTCRoleAudience];[self.trtcCloud stopLocalAudio];} else {// 로컬 마이크 순위 목록을 업데이트하고 로컬 마이크 순위 뷰 렌더링합니다}}}}
// 로컬에 저장된 전체 마이크 순위 정보의 목록@property (nonatomic, copy) NSArray<SeatInfoModel *> *seatInfoArray;// 스트리머 측에서 해당 인터페이스를 호출하여 그룹 속성에 저장된 마이크 순위 정보를 수정합니다.- (void)muteSeatWithIndex:(NSInteger)seatIndex mute:(BOOL)mute {// 마이크 순위 정보 인스턴스 생성하며 수정된 마이크 순위 정보를 저장합니다SeatInfoModel *localInfo = self.seatInfoArray[seatIndex];SeatInfoModel *seatInfo = [[SeatInfoModel alloc] init];seatInfo.status = localInfo.status;seatInfo.mute = mute;seatInfo.userId = localInfo.userId;// 마이크 순위 정보 객체를 JSON 형식으로 직렬화합니다NSString *jsonStr = seatInfo.toJSONString;NSDictionary *dict = @{ [NSString stringWithFormat:@"seat%ld", seatIndex]: jsonStr };// 그룹 속성 설정합니다. 해당 그룹 속성이 이미 있으면 value 값을 업데이트하고 없으면 해당 속성을 추가합니다[[V2TIMManager sharedInstance] setGroupAttributes:self.groupId attributes:dict succ:^{// 그룹 속성의 수정이 성공되고 onGroupAttributeChanged 콜백 트리거됩니다} fail:^(int code, NSString *desc) {// 그룹 속성의 수정이 실패되고 마이크 금언 실패됩니다}];}// 연결된 청취자 측에서 그룹 속성 변경 콜백을 수신하여 자체 정보에 매칭 성공 후 스트리밍 일시 중지/재개합니다[[V2TIMManager sharedInstance] addGroupListener:self];- (void)onGroupAttributeChanged:(NSString *)groupID attributes:(NSMutableDictionary<NSString *,NSString *> *)attributes {// 로컬에 저장된 기존의 전체 마이크 순위 정보 리스트NSArray *oldSeatArray = self.seatInfoArray;// groupAttributeMap에서 파싱한 최신 전체 마이크 순위 정보 리스트NSArray *newSeatArray = [self getSeatListFromAttr:attributes seatSize:self.seatSize];// 전체 마이크 순위 정보 리스트를 순회하며 새/구 마이크 정보를 비교합니다.for (int i = 0; i < self.seatSize; i++) {SeatInfoModel *oldInfo = oldSeatArray[i];SeatInfoModel *newInfo = newSeatArray[i];if (oldInfo.mute != newInfo.mute) {if ([newInfo.userId isEqualToString:self.userId]) {// 자신의 정보에 매칭 성공 후 로컬 스트리밍을 일시 중지/재개합니다.[self.trtcCloud muteLocalAudio:newInfo.mute];} else {// 로컬 마이크 순위 목록을 업데이트하고 로컬 마이크 순위 뷰 렌더링합니다}}}}
// 로컬에 저장된 전체 마이크 순위 정보의 목록@property (nonatomic, copy) NSArray<SeatInfoModel *> *seatInfoArray;// 스트리머 측에서 해당 인터페이스를 호출하여 그룹 속성에 저장된 마이크 순위 정보를 수정합니다.- (void)lockSeatWithIndex:(NSInteger)seatIndex isLock:(BOOL)isLock {// 마이크 순위 정보 인스턴스 생성하며 수정된 마이크 순위 정보를 저장합니다SeatInfoModel *localInfo = self.seatInfoArray[seatIndex];SeatInfoModel *seatInfo = [[SeatInfoModel alloc] init];seatInfo.status = isLock? SeatInfoStatusLocked : SeatInfoStatusUnused;seatInfo.mute = localInfo.mute;seatInfo.userId = @"";// 마이크 순위 정보 객체를 JSON 형식으로 직렬화합니다NSString *jsonStr = seatInfo.toJSONString;NSDictionary *dict = @{ [NSString stringWithFormat:@"seat%ld", seatIndex]: jsonStr };// 그룹 속성 설정합니다. 해당 그룹 속성이 이미 있으면 value 값을 업데이트하고 없으면 해당 속성을 추가합니다[[V2TIMManager sharedInstance] setGroupAttributes:self.groupId attributes:dict succ:^{// 그룹 속성의 수정이 성공되고 onGroupAttributeChanged 콜백 트리거됩니다} fail:^(int code, NSString *desc) {// 그룹 속성의 수정이 실패되고 마이크 잠금이 실패됩니다}];}// 청취자 측에서 그룹 속성 변경 콜백을 수신하여 해당 마이크 뷰가 업데이트됩니다[[V2TIMManager sharedInstance] addGroupListener:self];- (void)onGroupAttributeChanged:(NSString *)groupID attributes:(NSMutableDictionary<NSString *,NSString *> *)attributes {// 로컬에 저장된 기존의 전체 마이크 순위 정보 리스트NSArray *oldSeatArray = self.seatInfoArray;// groupAttributeMap에서 파싱한 최신 전체 마이크 순위 정보 리스트NSArray *newSeatArray = [self getSeatListFromAttr:attributes seatSize:self.seatSize];// 전체 마이크 순위 정보 리스트를 순회하며 새/구 마이크 정보를 비교합니다.for (int i = 0; i < self.seatSize; i++) {SeatInfoModel *oldInfo = oldSeatArray[i];SeatInfoModel *newInfo = newSeatArray[i];if (oldInfo.status == SeatInfoStatusLocked && newInfo.status == SeatInfoStatusUnused) {// 마이크 잠금의 해제} else if (oldInfo.status != newInfo.status && newInfo.status == SeatInfoStatusLocked) {// 마이크 순위 잠그기}}}
// 로컬에 저장된 전체 마이크 순위 정보의 목록@property (nonatomic, copy) NSArray<SeatInfoModel *> *seatInfoArray;// 마이크 사용중의 스트리머가 해당 인터페이스를 호출하여 그룹 속성에 저장된 마이크 정보를 수정합니다.- (void)moveSeatToIndex:(NSInteger)dstIndex {// userId로 소스 마이크 번호를 받습니다__block NSInteger srcIndex = -1;[self.seatInfoArray enumerateObjectsUsingBlock:^(SeatInfoModel * _Nonnull seatInfo, NSUInteger idx, BOOL * _Nonnull stop) {if ([seatInfo.userId isEqualToString:self.userId]) {srcIndex = idx;*stop = YES;}}];if (srcIndex < 0 || dstIndex < 0 || dstIndex >= self.seatInfoArray.count) {return;}// 마이크 번호로 해당 마이크 순위를 받습니다SeatInfoModel *srcSeatInfo = self.seatInfoArray[srcIndex];SeatInfoModel *dstSeatInfo = self.seatInfoArray[dstIndex];// 마이크 위치 정보 인스턴스를 생성하고 수정된 소스 마이크 순위 정보를 저장합니다SeatInfoModel *srcChangeInfo = [[SeatInfoModel alloc] init];srcChangeInfo.status = SeatInfoStatusUnused;srcChangeInfo.mute = srcSeatInfo.mute;srcChangeInfo.userId = @"";// 마이크 순위 정보 인스턴스를 생성하고 수정된 대상 마이크 순위 정보를 저장합니다SeatInfoModel *dstChangeInfo = [[SeatInfoModel alloc] init];dstChangeInfo.status = SeatInfoStatusUsed;dstChangeInfo.mute = dstSeatInfo.mute;dstChangeInfo.userId = self.userId;// 마이크 순위 정보 객체를 JSON 형식으로 직렬화합니다NSString *srcJsonStr = srcChangeInfo.toJSONString;NSString *dstJsonStr = dstChangeInfo.toJSONString;NSDictionary *dict = @{ [NSString stringWithFormat:@"seat%ld", srcIndex]: srcJsonStr,[NSString stringWithFormat:@"seat%ld", dstIndex]: dstJsonStr};// 그룹 속성을 설정하고 해당 그룹 속성이 이미 있으면 value 값을 업데이트하고, 없으면 해당 속성을 추가합니다.[[V2TIMManager sharedInstance] setGroupAttributes:self.groupId attributes:dict succ:^{// 그룹 속성의 수정이 성공되며 마이크 이동이 성공됩니다} fail:^(int code, NSString *desc) {// 그룹 속성의 수정이 실패되고 마이크 이동이 실패됩니다}];}
muteRemoteAudio(userId, mute)를 추가로 호출하여 원격 사용자의 오디오 스트림을 구독하고 재생해야 합니다.// 자동 구독 모드(기본값)[self.trtcCloud setDefaultStreamRecvMode:YES video:YES];// 수동 구독 모드(자체 정의)[self.trtcCloud setDefaultStreamRecvMode:NO video:NO];
setDefaultStreamRecvMode을 설정하려면 방 입장 enterRoom 전에 호출해야만 적용시켜야 합니다.// 로컬 오디오의 수집 및 게시를 활성화합니다[self.trtcCloud startLocalAudio:TRTCAudioQualityDefault];// 로컬 오디오의 수집 및 게시를 중지합니다[self.trtcCloud stopLocalAudio];
startLocalAudio는 마이크 사용 권한을 요청하며, stopLocalAudio는 마이크 사용 권한을 릴리스합니다.// 로컬 오디오 스트림 게시를 일시 중지합니다(마이크 끄기)[self.trtcCloud muteLocalAudio:YES];// 로컬 오디오 스트림 게시를 재개합니다(마이크 켜기)[self.trtcCloud muteLocalAudio:NO];// 특정 원격 사용자의 오디오 스트림 구독 및 재생을 일시 중지합니다[self.trtcCloud muteRemoteAudio:userId mute:YES];// 특정 원격 사용자의 오디오 스트림 구독 및 재생을 재개합니다[self.trtcCloud muteRemoteAudio:userId mute:NO];// 모든 원격 사용자의 오디오 스트림 구독 및 재생을 일시 중지합니다[self.trtcCloud muteAllRemoteAudio:YES];// 모든 원격 사용자의 오디오 스트림 구독 및 재생을 재개합니다[self.trtcCloud muteAllRemoteAudio:NO];
muteLocalAudio는 소프트웨어 측면에서 데이터 스트림을 일시 중지하거나 허용하기만 하면 되므로 효율적이고 원활합니다.자주 마이크를 켜고 끄는 시나리오에 더 적합합니다.// 로컬 오디오 수집 및 게시 시 음질을 설정합니다[self.trtcCloud startLocalAudio:TRTCAudioQualityDefault];// 오디오 스트리밍 중 종적으로 음질을 설정합니다[self.trtcCloud setAudioQuality:TRTCAudioQualityDefault];
// 음량 유형의 설정[self.trtcCloud setSystemVolumeType:TRTCSystemVolumeTypeAuto];
// 오디오 라우팅의 설정[self.trtcCloud setAudioRoute:TRTCAudioModeSpeakerphone];
// 공개 탄막 메시지의 전송[[V2TIMManager sharedInstance] sendGroupTextMessage:text to:groupID priority:V2TIM_PRIORITY_NORMAL succ:^{// 탄막 메시지의 전송이 성공됩니다} fail:^(int code, NSString *desc) {// 탄막 메시지의 전송이 실패됩니다}];// 공개 탄막 메시지의 수신[[V2TIMManager sharedInstance] addSimpleMsgListener:self];- (void)onRecvGroupTextMessage:(NSString *)msgID groupID:(NSString *)groupID sender:(V2TIMGroupMemberInfo *)info text:(NSString *)text {NSLog(@"%@: %@", info.nickName, text);}
// 볼륨 크기 콜백 활성화하고 방 입장 성공 후 즉시 활성화하는 것을 권장합니다// interval: 콜백 간격(ms); enable_vad: 인간 음성 검사의 활성화 여부[self.trtcCloud enableAudioVolumeEvaluation:interval enable_vad:enable_vad];self.trtcCloud.delegate = self;- (void)onUserVoiceVolume:(NSArray<TRTCVolumeInfo *> *)userVolumes totalVolume:(NSInteger)totalVolume {// userVolumes는 로컬 사용자와 원격 스트리밍 사용자를 포함한 모든 말하고 있는 사용자의 볼륨 크기를 관리합니다// totalVolume는 원격 스트리밍 사용자 중 최대 볼륨 값을 피드백하는 데 사용됩니다...// 볼륨 크기에 따라 UI에 해당하는 음파 디스플레이를 표시합니다....}
userVolumes는 배열이며 배열의 각 요소에서 userId가 비어 있으면 로컬 마이크에서 수집한 볼륨 크기가 너무 적다는 것을 나타내고, userId가 비어 있지 않으면 원격 사용자의 볼륨 크기가 너무 적다는 것을 나타냅니다.// 배경 음악, 짧은 음향 효과 및 인간음성 이펙트를 설정하는 데 사용되는 관리 클래스 얻습니다self.audioEffectManager = [self.trtcCloud getAudioEffectManager];TXAudioMusicParam *param = [[TXAudioMusicParam alloc] init];param.ID = musicID;param.path = musicPath;// 음악을 원격으로 게시할지?(그렇지 않으면 로컬에서만 재생됨)param.publish = YES;// 재생 중인 파일이 짧은 음향 효과 파일인지?param.isShortFile = NO;// 배경 음악의 재생 시작합니다__weak typeof(self) weakSelf = self;[self.audioEffectManager startPlayMusic:param onStart:^(NSInteger errCode) {__strong typeof(weakSelf) strongSelf = weakSelf;// 재생 시작 콜백// -4001: 경로 열기 실패// -4002: 디코딩 실패// -4003: URL 주소 무효// -4004: 재생 중지되지 않음if (errCode < 0) {// 재생 실패 후 다시 재생하기 전에 현재 음악 재생을 먼저 중지해야 합니다.[strongSelf.audioEffectManager stopPlayMusic:musicID];}} onProgress:^(NSInteger progressMs, NSInteger durationMs) {// 재생 진도 콜백// progressMs 현재 재생 시간(밀리초)// durationMs 현재 음악의 총 시간(밀리초)} onComplete:^(NSInteger errCode) {// 재생 종료 콜백// 약한 네트워크 상태로 인해 재생 중간에 실패한 경우에도 이 콜백이 발생하며 이때 errCode < 0입니다// 재생 중간에 일시 정지하거나 중지해도 onComplete 콜백이 발생하지 않습니다}];// 배경 음악의 재생 중지합니다[self.audioEffectManager stopPlayMusic:musicID];// 배경 음악의 재생을 일시 정지합니다[self.audioEffectManager pausePlayMusic:musicID];// 배경 음악의 재생 재개합니다[self.audioEffectManager resumePlayMusic:musicID];
musicPath를 통해 로컬 절대 경로 또는 URL 주소를 전달할 수 있습니다. MP3/AAC/M4A/WAV 형식을 지원합니다.// 특정 배경 음악의 로컬 재생 음량 크기를 설정합니다[self.audioEffectManager setMusicPlayoutVolume:musicID volume:volume];// 특정 배경 음악의 원격 재생 음량 크기를 설정합니다[self.audioEffectManager setMusicPublishVolume:musicID volume:volume];// 모든 배경 음악의 로컬 음량 및 원격 음량 크기를 설정합니다[self.audioEffectManager setAllMusicVolume:volume];// 인간 음성을 수집하는 음량 크기를 설정합니다[self.audioEffectManager setVoiceVolume:volume];
muteLocalAudio(true) 아니고 setVoiceVolume(0)를 사용합니다.AudioMusicParam의 loopCount 매개변수를 사용하여 반복 재생 횟수를 설정합니다.- (void)startPlayMusicWithId:(int32_t)musicId path:(NSString *)path loopCount:(NSInteger)loopCount {TXAudioMusicParam *param = [[TXAudioMusicParam alloc] init];param.ID = musicId;param.path = path;param.publish = YES;// 재생 중인 파일이 짧은 음향 효과 파일인지?param.isShortFile = YES;// 반복 재생 횟수를 설정합니다. 음수는 무한 반복을 의미합니다param.loopCount = loopCount < 0 ? NSIntegerMax : loopCount;[self.audioEffectManager startPlayMusic:param onStart:nil onProgress:nil onComplete:nil];}
onComplete 콜백이 트리거되지 않으며 설정된 반복 횟수가 모두 완료된 후에야 해당 콜백이 트리거됩니다.onComplete을 통해 반복 재생을 구현하며 일반적으로 리스트 반복 또는 단곡 반복에 사용됩니다.- (void)repeatPlayMusicWithParam:(TXAudioMusicParam *)param {__weak typeof(self) weakSelf = self;[self.audioEffectManager startPlayMusic:param onStart:nil onProgress:nil onComplete:^(NSInteger errCode) {__strong typeof(weakSelf) strongSelf = weakSelf;// 여기서 재생 인터페이스를 다시 호출하여 음악을 반복 재생할 수 있습니다.if (errCode >= 0) {[strongSelf repeatPlayMusicWithParam:param];}}];}
- (void)startPublishMediaToRoom:(NSString *)roomId userID:(NSString *)userId {// 미디어 스트림 발행의 목적지 주소TRTCPublishTarget *target = [[TRTCPublishTarget alloc] init];// 혼합 스트림 후 방으로 리턴 전송target.mode = TRTCPublishMixStreamToRoom;target.mixStreamIdentity.strRoomId = roomId;// 혼합 스트림 로봇의 userid는 방 내 다른 사용자의 userid와 중복되면 안됩니다target.mixStreamIdentity.userId = [NSString stringWithFormat:@"%@%@", userId, MIX_ROBOT];TRTCStreamEncoderParam* encoderParam = [[TRTCStreamEncoderParam alloc] init];// 트랜스코딩된 오디오 스트림의 인코딩 매개변수를 설정합니다(사용자 자체 정의 가능)encoderParam.audioEncodedSampleRate = 48000;encoderParam.audioEncodedChannelNum = 2;encoderParam.audioEncodedKbps = 64;encoderParam.audioEncodedCodecType = 2;// 트랜스코팅된 비디오 스트림의 인코딩 매개변수를 설정합니다(순수 오디오및 믹싱혼합 스트림의 경우는 무시해도 됩니다)encoderParam.videoEncodedWidth = 64;encoderParam.videoEncodedHeight = 64;encoderParam.videoEncodedFPS = 15;encoderParam.videoEncodedGOP = 3;encoderParam.videoEncodedKbps = 30;// 오디오/비디오 혼합 스트리밍 매개변수를 설정합니다TRTCStreamMixingConfig *config = [[TRTCStreamMixingConfig alloc] init];// 기본적으로 빈 값을 입력하면 되고 방의 모든 오디오가 믹싱됨을 의미합니다config.audioMixUserList = nil;// 비디오 혼합 스트림 템플릿을 설정합니다(순수 오디오및 믹싱혼합 스트림의 경우는 무시해도 됩니다)TRTCVideoLayout *layout = [[TRTCVideoLayout alloc] init];config.videoLayoutList = @[layout];// 혼합 스트림의 전송이 시작됩니다[self.trtcCloud startPublishMediaStream:target encoderParam:encoderParam mixingConfig:config];}
#pragma mark - TRTCCloudDelegate- (void)onStartPublishMediaStream:(NSString *)taskId code:(int)code message:(NSString *)message extraInfo:(NSDictionary *)extraInfo {// taskId: 요청이 성공하면 RTC Engine 백엔드는 콜백에서 이 작업의 taskId를 제공합니다. 다음에 이 taskId를 updatePublishMediaStream 및 stopPublishMediaStream과 함께 사용하여 업데이트 및 중지할 수 있습니다.// code: 콜백 결과.0은 성공을 나타내며 그 외의 값은 실패를 나타냅니다.}- (void)onUpdatePublishMediaStream:(NSString *)taskId code:(int)code message:(NSString *)message extraInfo:(NSDictionary *)extraInfo {// 미디어 스트림 발생 인터페이스(updatePublishMediaStream)를 호출할 때 전달한 taskId는 이 콜백을 통해 다시 전달되며 이 콜백이 어떤 업데이트 요청에 속하는지 식별하는 데 사용됩니다.// code: 콜백 결과.0은 성공을 나타내며 그 외의 값은 실패를 나타냅니다.}- (void)onStopPublishMediaStream:(NSString *)taskId code:(int)code message:(NSString *)message extraInfo:(NSDictionary *)extraInfo {// 미디어 스트림 중지 인터페이스(stopPublishMediaStream)를 호출할 때 전달한 taskId는 이 콜백을 통해 다시 전달되며 이 콜백이 어떤 중지 요청에 속하는지 식별하는 데 사용됩니다.// code: 콜백 결과. 0은 성공을 나타내며, 그 외의 값은 실패를 나타냅니다.}
startPublishMediaStream로 시작된 미디어 스트림을 업데이트합니다.// taskId: onStartPublishMediaStream 콜백의 작업 ID// target: 예를 들어 발행된 CDN URL 추가 또는 삭제// params: 재생 측의 스트림 중단을 방지하기 위해 미디어 스트림 인코딩 출력 매개변수를 일치하게 유지하세요.// config: 예를 들어 크로스 룸 PK와 같은혼합 스트림 트랜스코딩에 참여하는 사용자 목록 업데이트합니다[self.trtcCloud updatePublishMediaStream:taskId publishTarget:target encoderParam:trtcStreamEncoderParam mixingConfig:trtcStreamMixingConfig];
startPublishMediaStream로 시작된 미디어 스트림을 중지합니다.// taskId: onStartPublishMediaStream 콜백의 작업 ID[self.trtcCloud stopPublishMediaStream:taskId];
startPublishMediaStream로 시작된 해당 사용자의 모든 미디어 스트림을 중지합니다. 하나의 미디어 스트림만 시작했거나 손님을 통해 시작된 모든 미디어 스트림을 중지하려는 경우 이 방법을 사용하는 것이 좋습니다.onNetworkQuality를 통해 로컬 및 원격 사용자의 네트워크 상태를 실시간으로 모니터링할 수 있으며 이 콜백은 2초마다 한 번씩 발생합니다.#pragma mark - TRTCCloudDelegate- (void)onNetworkQuality:(TRTCQualityInfo *)localQuality remoteQuality:(NSArray<TRTCQualityInfo *> *)remoteQuality {// localQuality userId가 비어 있으면 로컬 사용자의 네트워크 상태에 대한 평가 결과를 나타냅니다.// remoteQuality는 원격 사용자의 네트워크 상태에 대한 평가 결과를 나타내며 그 결과는 원격 및 로컬 양쪽의 영향을 다 받습니다.switch(localQuality.quality) {case TRTCQuality_Unknown:NSLog(@"정의되지 않음");break;case TRTCQuality_Excellent:NSLog(@"현재 네트워크 상태가 매우 좋음");break;case TRTCQuality_Good:NSLog(@"현재 네트워크 상태가 비교적 좋음");break;case TRTCQuality_Poor:NSLog(@"현재 네트워크 상태가 보통임");break;case TRTCQuality_Bad:NSLog(@"현재 네트워크 상태가 나쁨");break;case TRTCQuality_Vbad:NSLog(@"현재 네트워크 상태가 매우 나쁨");break;case TRTCQuality_Down:NSLog(@"현재 네트워크가 RTC Engine 최소 요구 사항을 충족하지 못함");break;default:break;}}
TRTCParams *params = [[TRTCParams alloc] init];params.sdkAppId = SDKAppID;params.roomId = self.roomId;params.userId = self.userId;// 업무 백엔드에서 가져온 UserSigparams.userSig = [self getUserSig];// 업무 백엔드에서 얻은 PrivateMapKey입니다params.privateMapKey = [self getPrivateMapKey];params.role = TRTCRoleAudience;[self.trtcCloud enterRoom:params appScene:TRTCAppSceneVoiceChatRoom];
// 업무 백엔드에서 얻은 최신 PrivateMapKey를 역할 전환 인터페이스에 전달합니다[self.trtcCloud switchRole:TRTCRoleAnchor privateMapKey:[self getPrivateMapKey]];
열거형 | 값 | 설명 |
ERR_TRTC_INVALID_USER_SIG | -3320 | 방 입장 매개변수 userSig가 올바르지 않습니다. TRTCParams.userSig이 비어 있는지 확인하세요. |
ERR_TRTC_USER_SIG_CHECK_FAILED | -100018 | UserSig 검증에 실패했습니다. 매개변수 TRTCParams.userSig이 올바르게 입력되었는지 또는 만료되지 않았는지 확인하세요. |
열거형 | 값 | 설명 |
ERR_TRTC_CONNECT_SERVER_TIMEOUT | -3308 | 방 입장 요청이 시간 초과하는 경우, 네트워크 연결이 끊겼는지 또는 VPN이 켜져 있는지 확인하세요. 4G로 전환하여 테스트할 수도 있습니다. |
ERR_TRTC_INVALID_SDK_APPID | -3317 | 입장 매개변수 sdkAppId가 잘못되었습니다. TRTCParams.sdkAppId이 비어 있는지 확인하세요. |
ERR_TRTC_INVALID_ROOM_ID | -3318 | 입장 매개변수 roomId가 잘못되었습니다. TRTCParams.roomId 또는 TRTCParams.strRoomId이 비어 있는지 확인하세요. roomId와 strRoomId는 혼용할 수 없습니다. |
ERR_TRTC_INVALID_USER_ID | -3319 | 입장 매개변수 userId가 올바르지 않습니다. TRTCParams.userId이 비어 있는지 확인하세요. |
ERR_TRTC_ENTER_ROOM_REFUSED | -3340 | 입장 요청이 거부되었습니다. enterRoom을 연속적으로 호출하여 동일한 ID의 방에 입장했는지 확인하세요. |
열거형 | 값 | 설명 |
ERR_MIC_START_FAIL | -1302 | Windows 또는 Mac 장치에서 마이크 구성 프로그램(드라이버)이 비정상일 경우, 마이크 열 수가 없습니다. 장치를 비활성화한 후 다시 활성화하거나, 기기를 재시작하거나, 구성 프로그램을 업데이트하세요. |
ERR_SPEAKER_START_FAIL | -1321 | 스피커 열기가 실패됩니다. 예를 들어 Windows 또는 Mac 장치에서 스피커 구성 프로그램(드라이버)이 비정상일 경우, 장치를 비활성화한 후 다시 활성화하거나 기기를 재시작하거나 구성 프로그램을 업데이트하세요. |
ERR_MIC_OCCUPY | -1319 | 마이크가 사용 중입니다. 예를 들어 모바일 장치에서 통화 중일 때 마이크를 열 수가 없습니다. |
onConnectionLost 콜백을 수신한 후 로컬 마이크 순위 UI에서 네트워크 연결 끊김을 표시하여 사용자에게 알려줍니다. 동시에 로컬에서 타이머를 시작하고 설정된 시간 임계값을 초과한 후에도 onConnectionRecovery 콜백을 수신하지 못하면 네트워크가 계속 끊긴 상태입니다. 이때 로컬에서 마이크 종료 및 방 나가기 프로세스를 시작하고 사용자에게 방을 나갔음을 알리는 팝업을 보낸 후 페이지를 파기합니다. 네트워크 연결이 90초(기본값) 이상 끊어지면 타임아웃으로 인한 방 나가기가 트리거되며 RTC Engine 서버는 해당 사용자를 방에서 강제 퇴장시킵니다. 해당 사용자가 스트리머 역할인 경우 방 내 다른 사용자는 onRemoteUserLeaveRoom 콜백을 받게 됩니다.#pragma mark - TRTCCloudDelegate- (void)onConnectionLost {// SDK와 클라우드 간의 연결이 끊어졌습니다.}- (void)onTryToReconnect {// SDK가 클라우드에 다시 연결을 시도 중입니다.}- (void)onConnectionRecovery {// SDK와 클라우드 간의 연결이 복구되었습니다.}
// 스트리머 구독을 통해 마이크 사용자의 상태를 감지합니다[[V2TIMManager sharedInstance] subscribeUserStatus:userList succ:^{// 스트리머 구독 사용자의 상태가 성공합니다} fail:^(int code, NSString *desc) {// 스트리머 구독 사용자의 상태가 실패합니다}];// 스트리머 구독을 통해 마이크 사용자의 상태 취소합니다[[V2TIMManager sharedInstance] unsubscribeUserStatus:userList succ:^{// 스트리머 구독 사용자의 상태룰 취소하는 것이 성공합니다} fail:^(int code, NSString *desc) {// 스트리머 구독 사용자의 상태를 취소하는 것이 실패합니다.}];// 사용자 상태 변경의 알림 및 처리[[V2TIMManager sharedInstance] addIMSDKListener:self];- (void)onUserStatusChanged:(NSArray<V2TIMUserStatus *> *)userStatusList {for (V2TIMUserStatus *userStatus in userStatusList) {NSString *userId = userStatus.userID;V2TIMUserStatusType status = userStatus.statusType;if (status == V2TIM_USER_STATUS_OFFLINE) {// 오프라인 상태에서 마이크 사용 끄게 시킵니다[self kickSeatWithIndex:[self getSeatIndexWithUserId:userId]];}}}

subscribeUserStatus 호출 시 오류가 발생합니다.https://trtc.tencentcloudapi.com/?Action=RemoveUser&SdkAppId=1400000001&RoomId=1234&UserIds.0=test1&UserIds.1=test2&<공통 요청 매개변수>
onExitRoom() 콜백을 수신하며 reason 값은 1입니다. 이때 해당 콜백에서 마이크 사용 종료및 Chat 그룹 퇴장 등의 작업을 처리할 수 있습니다.// RTC Engine 방 이탈 이벤트의 콜백- (void)onExitRoom:(NSInteger)reason {if (reason == 0) {// exitRoom을 호출하여 방에서 나가기.NSLog(@"Exit current room by calling the 'exitRoom' api of sdk ...");} else {// reason 1: 서버에 의해 현재 방에서 나가게 됩니다// reason 2: 현재 방 전체가 해산됩니다NSLog(@"Kicked out of the current room by server or current room is dissolved ...");// 마이크 사용 종료[self leaveSeatWithIndex:seatIndex];// Chat 그룹에서 나가기[[V2TIMManager sharedInstance] quitGroup:groupID succ:^{//그룹 나가기 성공} fail:^(int code, NSString *desc) {// 그룹 나가기 실패}];}}
https://xxxxxx/v4/group_open_http_svc/destroy_group?sdkappid=88888888&identifier=admin&usersig=xxx&random=99999999&contenttype=json
onGroupDismissed() 콜백을 받게 됩니다. 이때 해당 콜백에서 RTC Engine 방 나가기 등의 작업을 처리할 수 있습니다.// 그룹 해산 콜백[[V2TIMManager sharedInstance] addGroupListener:self];- (void)onGroupDismissed:(NSString *)groupID opUser:(V2TIMGroupMemberInfo *)opUser {// RTC Engine 방 나가기[self.trtcCloud stopLocalAudio];[self.trtcCloud exitRoom];}
exitRoom()을 호출하여 방 나가기를 완료하면 RTC Engine 방이 자동으로 해산됩니다. 물론 서버 측의 인터페이스 DismissRoom(정수형 방 번호) 또는 DismissRoomByStrRoomId(문자열 방 ID)를 호출하여 RTC Engine 방을 강제로 해산시킬 수도 있습니다.
V2TIMMessageListGetOption *option = [[V2TIMMessageListGetOption alloc] init];option.getType = V2TIM_GET_CLOUD_OLDER_MSG; // 클라우드의 이전 메시지 가져오기option.getTimeBegin = 1640966400; // 2022-01-01 00:00:00부터 시작option.getTimePeriod = 1 * 24 * 60 * 60; // 하루 종일의 메시지 가져오기option.count = INT_MAX; // 시간 범위 내 모든 메시지로 반환하기option.groupID = #your group id#; // 그룹 채팅 메시지 가져오기[V2TIMManager.sharedInstance getHistoryMessageList:option succ:^(NSArray<V2TIMMessage *> *msgs) {NSLog(@"success");} fail:^(int code, NSString *desc) {NSLog(@"failure, code:%d, desc:%@", code, desc);}];
onUserAudioAvailable(userId, true) 콜백을 통해 해당 스트리머의 무음상태를 해제합니다.- (void)onUserAudioAvailable:(NSString *)userId available:(BOOL)available {if (available) {// 해당 스트리머의 무음 상태를 해제합니다}}
[[V2TIMManager sharedInstance] getGroupAttributes:groupID keys:nil succ:^(NSMutableDictionary<NSString *,NSString *> *groupAttributeList) {// 그룹 속성 가져오기가 성공되며 스트리머 무음 상태를 저장하는 키를 muteStatus로 가정합니다NSString *muteStatus = groupAttributeList[@"muteStatus"];// muteStatus를 분석하여 각 마이크를 사용하는 스트리머의 무음 상태를 가져옵니다} fail:^(int code, NSString *desc) {// 그룹 속성 가져오기가 실패됩니다}];
피드백