Commit e7f548f1d5245da872b78bf6d4d837bb78cb24cf

Authored by 王军波
1 parent b14c0be3

更新

Showing 41 changed files with 1388 additions and 273 deletions
CNLiveChatSDKDemo/CNLiveChatManager.framework/CNLiveChatManager deleted 100755 → 0
No preview for this file type
CNLiveChatSDKDemo/CNLiveChatSDKDemo.xcodeproj/project.pbxproj
... ... @@ -7,12 +7,13 @@
7 7 objects = {
8 8  
9 9 /* Begin PBXBuildFile section */
10   - D214CB431EF7AD490014EEBA /* CNLiveMsgTools.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D214CB421EF7AD490014EEBA /* CNLiveMsgTools.framework */; };
11   - D214CB451EF7AD4F0014EEBA /* CNLiveChatManager.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D214CB441EF7AD4F0014EEBA /* CNLiveChatManager.framework */; };
12   - D214CB461EF7AD560014EEBA /* CNLiveMsgTools.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D214CB421EF7AD490014EEBA /* CNLiveMsgTools.framework */; };
13   - D214CB471EF7AD560014EEBA /* CNLiveMsgTools.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = D214CB421EF7AD490014EEBA /* CNLiveMsgTools.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
14   - D214CB491EF7AD580014EEBA /* CNLiveChatManager.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D214CB441EF7AD4F0014EEBA /* CNLiveChatManager.framework */; };
15   - D214CB4A1EF7AD580014EEBA /* CNLiveChatManager.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = D214CB441EF7AD4F0014EEBA /* CNLiveChatManager.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
  10 + D20E286F1F1C914500612B90 /* CNLiveImageTableViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = D20E286E1F1C914500612B90 /* CNLiveImageTableViewCell.m */; };
  11 + D20E28721F1C915D00612B90 /* CNLiveVoiceTableViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = D20E28711F1C915D00612B90 /* CNLiveVoiceTableViewCell.m */; };
  12 + D20E28781F1C9AAE00612B90 /* CNLiveChatManager.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D20E28771F1C9AAE00612B90 /* CNLiveChatManager.framework */; };
  13 + D20E287D1F1C9AB600612B90 /* CNLiveChatManager.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = D20E28771F1C9AAE00612B90 /* CNLiveChatManager.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
  14 + D20E28851F1D317900612B90 /* CNLiveMsgTools.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D20E28841F1D317900612B90 /* CNLiveMsgTools.framework */; };
  15 + D20E28871F1D317D00612B90 /* CNLiveMsgTools.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = D20E28841F1D317900612B90 /* CNLiveMsgTools.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
  16 + D20E28891F1D31E300612B90 /* tu.jpg in Resources */ = {isa = PBXBuildFile; fileRef = D20E28881F1D31E300612B90 /* tu.jpg */; };
16 17 D2239CD41EE94F31005572FB /* praiseModel.m in Sources */ = {isa = PBXBuildFile; fileRef = D2239CD31EE94F31005572FB /* praiseModel.m */; };
17 18 D231941F1E70101500111C3B /* MessageModel.m in Sources */ = {isa = PBXBuildFile; fileRef = D231941E1E70101500111C3B /* MessageModel.m */; };
18 19 D231C8A61E6FFC2700EAC427 /* ChatRoomViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = D231C8A51E6FFC2700EAC427 /* ChatRoomViewController.m */; };
... ... @@ -28,14 +29,14 @@
28 29 /* End PBXBuildFile section */
29 30  
30 31 /* Begin PBXCopyFilesBuildPhase section */
31   - D214CB481EF7AD560014EEBA /* Embed Frameworks */ = {
  32 + D20E287B1F1C9AB300612B90 /* Embed Frameworks */ = {
32 33 isa = PBXCopyFilesBuildPhase;
33 34 buildActionMask = 2147483647;
34 35 dstPath = "";
35 36 dstSubfolderSpec = 10;
36 37 files = (
37   - D214CB471EF7AD560014EEBA /* CNLiveMsgTools.framework in Embed Frameworks */,
38   - D214CB4A1EF7AD580014EEBA /* CNLiveChatManager.framework in Embed Frameworks */,
  38 + D20E287D1F1C9AB600612B90 /* CNLiveChatManager.framework in Embed Frameworks */,
  39 + D20E28871F1D317D00612B90 /* CNLiveMsgTools.framework in Embed Frameworks */,
39 40 );
40 41 name = "Embed Frameworks";
41 42 runOnlyForDeploymentPostprocessing = 0;
... ... @@ -43,8 +44,13 @@
43 44 /* End PBXCopyFilesBuildPhase section */
44 45  
45 46 /* Begin PBXFileReference section */
46   - D214CB421EF7AD490014EEBA /* CNLiveMsgTools.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = CNLiveMsgTools.framework; sourceTree = "<group>"; };
47   - D214CB441EF7AD4F0014EEBA /* CNLiveChatManager.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = CNLiveChatManager.framework; sourceTree = "<group>"; };
  47 + D20E286D1F1C914500612B90 /* CNLiveImageTableViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CNLiveImageTableViewCell.h; sourceTree = "<group>"; };
  48 + D20E286E1F1C914500612B90 /* CNLiveImageTableViewCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CNLiveImageTableViewCell.m; sourceTree = "<group>"; };
  49 + D20E28701F1C915D00612B90 /* CNLiveVoiceTableViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CNLiveVoiceTableViewCell.h; sourceTree = "<group>"; };
  50 + D20E28711F1C915D00612B90 /* CNLiveVoiceTableViewCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CNLiveVoiceTableViewCell.m; sourceTree = "<group>"; };
  51 + D20E28771F1C9AAE00612B90 /* CNLiveChatManager.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = CNLiveChatManager.framework; sourceTree = "<group>"; };
  52 + D20E28841F1D317900612B90 /* CNLiveMsgTools.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = CNLiveMsgTools.framework; sourceTree = "<group>"; };
  53 + D20E28881F1D31E300612B90 /* tu.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = tu.jpg; sourceTree = "<group>"; };
48 54 D2239CD21EE94F31005572FB /* praiseModel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = praiseModel.h; sourceTree = "<group>"; };
49 55 D2239CD31EE94F31005572FB /* praiseModel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = praiseModel.m; sourceTree = "<group>"; };
50 56 D231941D1E70101500111C3B /* MessageModel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MessageModel.h; sourceTree = "<group>"; };
... ... @@ -75,16 +81,26 @@
75 81 isa = PBXFrameworksBuildPhase;
76 82 buildActionMask = 2147483647;
77 83 files = (
78   - D214CB431EF7AD490014EEBA /* CNLiveMsgTools.framework in Frameworks */,
79   - D214CB451EF7AD4F0014EEBA /* CNLiveChatManager.framework in Frameworks */,
80   - D214CB461EF7AD560014EEBA /* CNLiveMsgTools.framework in Frameworks */,
81   - D214CB491EF7AD580014EEBA /* CNLiveChatManager.framework in Frameworks */,
  84 + D20E28781F1C9AAE00612B90 /* CNLiveChatManager.framework in Frameworks */,
  85 + D20E28851F1D317900612B90 /* CNLiveMsgTools.framework in Frameworks */,
82 86 );
83 87 runOnlyForDeploymentPostprocessing = 0;
84 88 };
85 89 /* End PBXFrameworksBuildPhase section */
86 90  
87 91 /* Begin PBXGroup section */
  92 + D20E288A1F1D31F300612B90 /* Resource */ = {
  93 + isa = PBXGroup;
  94 + children = (
  95 + D264D5AC1E6FDE02002CDF41 /* Main.storyboard */,
  96 + D264D5AF1E6FDE02002CDF41 /* Assets.xcassets */,
  97 + D264D5B11E6FDE02002CDF41 /* LaunchScreen.storyboard */,
  98 + D264D5B41E6FDE02002CDF41 /* Info.plist */,
  99 + D20E28881F1D31E300612B90 /* tu.jpg */,
  100 + );
  101 + name = Resource;
  102 + sourceTree = "<group>";
  103 + };
88 104 D231941C1E700FEC00111C3B /* Controller */ = {
89 105 isa = PBXGroup;
90 106 children = (
... ... @@ -116,6 +132,10 @@
116 132 children = (
117 133 D244EFE81EE9246D00C1B9DB /* CNLiveCommentTableViewCell.h */,
118 134 D244EFE91EE9246D00C1B9DB /* CNLiveCommentTableViewCell.m */,
  135 + D20E286D1F1C914500612B90 /* CNLiveImageTableViewCell.h */,
  136 + D20E286E1F1C914500612B90 /* CNLiveImageTableViewCell.m */,
  137 + D20E28701F1C915D00612B90 /* CNLiveVoiceTableViewCell.h */,
  138 + D20E28711F1C915D00612B90 /* CNLiveVoiceTableViewCell.m */,
119 139 );
120 140 name = View;
121 141 sourceTree = "<group>";
... ... @@ -123,8 +143,6 @@
123 143 D264D5971E6FDE02002CDF41 = {
124 144 isa = PBXGroup;
125 145 children = (
126   - D214CB441EF7AD4F0014EEBA /* CNLiveChatManager.framework */,
127   - D214CB421EF7AD490014EEBA /* CNLiveMsgTools.framework */,
128 146 D264D5A21E6FDE02002CDF41 /* CNLiveChatSDKDemo */,
129 147 D264D5A11E6FDE02002CDF41 /* Products */,
130 148 );
... ... @@ -141,16 +159,15 @@
141 159 D264D5A21E6FDE02002CDF41 /* CNLiveChatSDKDemo */ = {
142 160 isa = PBXGroup;
143 161 children = (
  162 + D20E28841F1D317900612B90 /* CNLiveMsgTools.framework */,
  163 + D20E28771F1C9AAE00612B90 /* CNLiveChatManager.framework */,
144 164 D264D5A61E6FDE02002CDF41 /* AppDelegate.h */,
145 165 D264D5A71E6FDE02002CDF41 /* AppDelegate.m */,
146 166 D23194201E70101B00111C3B /* Model */,
147 167 D244EFEB1EE9247C00C1B9DB /* View */,
148 168 D231941C1E700FEC00111C3B /* Controller */,
149 169 D264D5BE1E6FDEED002CDF41 /* PrefixHeader.pch */,
150   - D264D5AC1E6FDE02002CDF41 /* Main.storyboard */,
151   - D264D5AF1E6FDE02002CDF41 /* Assets.xcassets */,
152   - D264D5B11E6FDE02002CDF41 /* LaunchScreen.storyboard */,
153   - D264D5B41E6FDE02002CDF41 /* Info.plist */,
  170 + D20E288A1F1D31F300612B90 /* Resource */,
154 171 D264D5A31E6FDE02002CDF41 /* Supporting Files */,
155 172 );
156 173 path = CNLiveChatSDKDemo;
... ... @@ -174,7 +191,7 @@
174 191 D264D59C1E6FDE02002CDF41 /* Sources */,
175 192 D264D59D1E6FDE02002CDF41 /* Frameworks */,
176 193 D264D59E1E6FDE02002CDF41 /* Resources */,
177   - D214CB481EF7AD560014EEBA /* Embed Frameworks */,
  194 + D20E287B1F1C9AB300612B90 /* Embed Frameworks */,
178 195 );
179 196 buildRules = (
180 197 );
... ... @@ -226,6 +243,7 @@
226 243 files = (
227 244 D264D5B31E6FDE02002CDF41 /* LaunchScreen.storyboard in Resources */,
228 245 D264D5B01E6FDE02002CDF41 /* Assets.xcassets in Resources */,
  246 + D20E28891F1D31E300612B90 /* tu.jpg in Resources */,
229 247 D264D5AE1E6FDE02002CDF41 /* Main.storyboard in Resources */,
230 248 );
231 249 runOnlyForDeploymentPostprocessing = 0;
... ... @@ -242,9 +260,11 @@
242 260 D2868FEC1EE914690037DECF /* CommentViewController.m in Sources */,
243 261 D231C8A91E6FFD3100EAC427 /* PrivateViewController.m in Sources */,
244 262 D264D5A51E6FDE02002CDF41 /* main.m in Sources */,
  263 + D20E28721F1C915D00612B90 /* CNLiveVoiceTableViewCell.m in Sources */,
245 264 D231C8A61E6FFC2700EAC427 /* ChatRoomViewController.m in Sources */,
246 265 D244EFEA1EE9246D00C1B9DB /* CNLiveCommentTableViewCell.m in Sources */,
247 266 D231941F1E70101500111C3B /* MessageModel.m in Sources */,
  267 + D20E286F1F1C914500612B90 /* CNLiveImageTableViewCell.m in Sources */,
248 268 D2239CD41EE94F31005572FB /* praiseModel.m in Sources */,
249 269 );
250 270 runOnlyForDeploymentPostprocessing = 0;
... ...
CNLiveChatSDKDemo/CNLiveChatSDKDemo.xcodeproj/xcuserdata/cnlive.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist
... ... @@ -2,38 +2,4 @@
2 2 <Bucket
3 3 type = "1"
4 4 version = "2.0">
5   - <Breakpoints>
6   - <BreakpointProxy
7   - BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
8   - <BreakpointContent
9   - shouldBeEnabled = "Yes"
10   - ignoreCount = "0"
11   - continueAfterRunningActions = "No"
12   - filePath = "CNLiveChatSDKDemo/CommentViewController.m"
13   - timestampString = "520502037.120796"
14   - startingColumnNumber = "9223372036854775807"
15   - endingColumnNumber = "9223372036854775807"
16   - startingLineNumber = "125"
17   - endingLineNumber = "125"
18   - landmarkName = "-textFieldShouldReturn:"
19   - landmarkType = "7">
20   - </BreakpointContent>
21   - </BreakpointProxy>
22   - <BreakpointProxy
23   - BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
24   - <BreakpointContent
25   - shouldBeEnabled = "Yes"
26   - ignoreCount = "0"
27   - continueAfterRunningActions = "No"
28   - filePath = "CNLiveChatSDKDemo/CommentViewController.m"
29   - timestampString = "520502037.120796"
30   - startingColumnNumber = "9223372036854775807"
31   - endingColumnNumber = "9223372036854775807"
32   - startingLineNumber = "131"
33   - endingLineNumber = "131"
34   - landmarkName = "-textFieldShouldReturn:"
35   - landmarkType = "7">
36   - </BreakpointContent>
37   - </BreakpointProxy>
38   - </Breakpoints>
39 5 </Bucket>
... ...
CNLiveChatSDKDemo/CNLiveChatSDKDemo/AppDelegate.m
... ... @@ -19,8 +19,9 @@
19 19 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
20 20  
21 21 // 必须初始化 但不要重复初始化
22   - [[CNLiveChatManager sharedCNLiveChatManager] initWithAppKey:@"a425987ebc86e352b3373c25d5bd082d0cc248b4043028" appId:@"60_irn9cdak77"];
23   -
  22 +// [[CNLiveChatManager sharedCNLiveChatManager] initWithAppKey:@"a425987ebc86e352b3373c25d5bd082d0cc248b4043028" appId:@"60_irn9cdak77"];
  23 + // 测试环境初始化(不要重复初始化)
  24 + [[CNLiveChatManager sharedCNLiveChatManager] initWithAppKey:@"a425987ebc86e352b3373c25d5bd082d0cc248b4043028" appId:@"60_irn9cdak77" isTestEnvironment:YES];
24 25  
25 26 // connectServer 连接服务器,相当于匿名游客身份登录
26 27 // 建议连接服务器操作写在 AppDelegate 里面
... ... @@ -38,17 +39,14 @@
38 39 // 除非您已经手动将连接断开,或者杀死程序,或者少数无法自动重连的情况,否则您不需要自己再手动重连。
39 40 // 客户端使用时可以判断一下当前用户的登录状态,未登录就用上面的 connectServer 的方法连接服务器,已登录就用 loginServer 此方法连接服务器;
40 41  
41   - CNLiveChatUserInfo *userInfo = [[CNLiveChatUserInfo alloc] initWithUserId:@"20170629" name:@"11" portrait:@""];
  42 + CNLiveChatUserInfo *userInfo = [[CNLiveChatUserInfo alloc] initWithUserId:@"20170717" name:@"11" portrait:@""];
42 43  
43 44 [[CNLiveChatManager sharedCNLiveChatManager] loginServer:userInfo success:^(NSString *userId) {
44 45  
45 46 NSLog(@"用户:%@ 已成功登陆",userId);
46   -
47   - // 更改昵称
48   - [CNLiveChatManager sharedCNLiveChatManager].currentUserInfo.name = @"小花";
  47 + [CNLiveChatManager sharedCNLiveChatManager].currentUserInfo.name = @"小强"; // 更改昵称
49 48  
50 49 } error:^(CNLiveChatConnectErrorCode errors) {
51   -
52 50 NSLog(@"登陆失败,错误码为:%ld",(long)errors);
53 51 }];
54 52  
... ...
CNLiveChatSDKDemo/CNLiveChatSDKDemo/Assets.xcassets/加号.imageset/Contents.json 0 → 100644
  1 +{
  2 + "images" : [
  3 + {
  4 + "idiom" : "universal",
  5 + "filename" : "加号.png",
  6 + "scale" : "1x"
  7 + },
  8 + {
  9 + "idiom" : "universal",
  10 + "scale" : "2x"
  11 + },
  12 + {
  13 + "idiom" : "universal",
  14 + "scale" : "3x"
  15 + }
  16 + ],
  17 + "info" : {
  18 + "version" : 1,
  19 + "author" : "xcode"
  20 + }
  21 +}
0 22 \ No newline at end of file
... ...
CNLiveChatSDKDemo/CNLiveChatSDKDemo/Assets.xcassets/加号.imageset/加号.png 0 → 100644

1.81 KB

CNLiveChatSDKDemo/CNLiveChatSDKDemo/Assets.xcassets/语音.imageset/Contents.json 0 → 100644
  1 +{
  2 + "images" : [
  3 + {
  4 + "idiom" : "universal",
  5 + "filename" : "语音.png",
  6 + "scale" : "1x"
  7 + },
  8 + {
  9 + "idiom" : "universal",
  10 + "scale" : "2x"
  11 + },
  12 + {
  13 + "idiom" : "universal",
  14 + "scale" : "3x"
  15 + }
  16 + ],
  17 + "info" : {
  18 + "version" : 1,
  19 + "author" : "xcode"
  20 + }
  21 +}
0 22 \ No newline at end of file
... ...
CNLiveChatSDKDemo/CNLiveChatSDKDemo/Assets.xcassets/语音.imageset/语音.png 0 → 100644

1.88 KB

CNLiveChatSDKDemo/CNLiveChatSDKDemo/Assets.xcassets/语音播.imageset/Contents.json 0 → 100644
  1 +{
  2 + "images" : [
  3 + {
  4 + "idiom" : "universal",
  5 + "filename" : "语音播.png",
  6 + "scale" : "1x"
  7 + },
  8 + {
  9 + "idiom" : "universal",
  10 + "scale" : "2x"
  11 + },
  12 + {
  13 + "idiom" : "universal",
  14 + "scale" : "3x"
  15 + }
  16 + ],
  17 + "info" : {
  18 + "version" : 1,
  19 + "author" : "xcode"
  20 + }
  21 +}
0 22 \ No newline at end of file
... ...
CNLiveChatSDKDemo/CNLiveChatSDKDemo/Assets.xcassets/语音播.imageset/语音播.png 0 → 100644

933 Bytes

CNLiveChatSDKDemo/CNLiveChatSDKDemo/Assets.xcassets/语音播放.imageset/Contents.json 0 → 100644
  1 +{
  2 + "images" : [
  3 + {
  4 + "idiom" : "universal",
  5 + "filename" : "语音播放.png",
  6 + "scale" : "1x"
  7 + },
  8 + {
  9 + "idiom" : "universal",
  10 + "scale" : "2x"
  11 + },
  12 + {
  13 + "idiom" : "universal",
  14 + "scale" : "3x"
  15 + }
  16 + ],
  17 + "info" : {
  18 + "version" : 1,
  19 + "author" : "xcode"
  20 + }
  21 +}
0 22 \ No newline at end of file
... ...
CNLiveChatSDKDemo/CNLiveChatSDKDemo/Assets.xcassets/语音播放.imageset/语音播放.png 0 → 100644

901 Bytes

CNLiveChatSDKDemo/CNLiveChatSDKDemo/CNLiveChatManager.framework/CNLiveChatManager 0 → 100755
No preview for this file type
CNLiveChatSDKDemo/CNLiveChatManager.framework/Headers/CNLiveChatManager.h renamed to CNLiveChatSDKDemo/CNLiveChatSDKDemo/CNLiveChatManager.framework/Headers/CNLiveChatManager.h
... ... @@ -10,6 +10,7 @@
10 10 #import "CNLiveChatUserInfo.h"
11 11 #import "CNLiveChatStatusDefine.h"
12 12 #import "CNLiveChatMessage.h"
  13 +#import "CNliveChatImageMessage.h"
13 14  
14 15 @protocol CNLiveChatManagerDelegate <NSObject>
15 16  
... ... @@ -45,7 +46,7 @@
45 46  
46 47 @param message 消息实体类型对象(包括消息内容,消息ID,会话类型,目标ID,发送者的用户信息)
47 48 */
48   -- (void)onReceived:(CNLiveChatMessage *)message;
  49 +- (void)onReceived:(id)message;
49 50  
50 51  
51 52 /**
... ... @@ -107,7 +108,7 @@
107 108  
108 109  
109 110 /**
110   - 初始化SDK方法
  111 + 初始化SDK方法(同上,区别:可以选择测试环境/上线环境)
111 112  
112 113 @param appKey 从视讯云平台获取到的appKey
113 114 @param appId 从视讯云平台获取到的appId
... ... @@ -199,22 +200,41 @@
199 200  
200 201  
201 202 /**
202   - 发送消息
  203 + 发送文本或语音消息
203 204  
204   - @param message 消息内容
  205 + @param message 消息内容(文本消息 CNLiveChatMessage / 语音消息 CNLiveChatVoiceMessage)
205 206 @param type 会话类型(私聊 / 聊天室)
206 207 @param targetId 会话目标ID(私聊:用户ID / 聊天室:聊天室ID)
207 208 @param successBlock 发送消息成功的回调,消息实体类型对象(包括消息内容,消息ID,会话类型,目标ID,发送者的用户信息)
208 209 @param errorBlock 发送消息失败的回调,返回错误码,消息ID,目标ID
209 210 */
210   -- (void)sendMessage:(NSString *)message
  211 +- (void)sendMessage:(id)message
211 212 type:(CNLiveConversationType)type
212 213 targetId:(NSString *)targetId
213   - success:(void (^)(CNLiveChatMessage *message))successBlock
  214 + success:(void (^)(id message))successBlock
214 215 error:(void (^)(CNLiveChatErrorCode errors, NSString *messageId, NSString *targetId))errorBlock;
215 216  
216 217  
217 218 /**
  219 + 发送图片消息
  220 +
  221 + @param type 会话类型(私聊 / 聊天室)
  222 + @param targetId 会话目标ID(私聊:用户ID / 聊天室:聊天室ID)
  223 + @param content 消息内容(图片类型 CNliveChatImageMessage)
  224 + @param progressBlock 消息发送进度更新的回调
  225 + [progress:当前的发送进度, 0 <= progress <= 100, messageId:消息的ID]
  226 + @param successBlock 消息发送成功的回调
  227 + @param errorBlock 消息发送失败的回调
  228 + */
  229 +- (void)sendMediaMessage:(CNLiveConversationType)type
  230 + targetId:(NSString *)targetId
  231 + content:(CNliveChatImageMessage *)content
  232 + progress:(void (^)(int progress, NSString * messageId))progressBlock
  233 + success:(void (^)(CNliveChatImageMessage * message))successBlock
  234 + error:(void (^)(CNLiveChatErrorCode errorCode, NSString * messageId))errorBlock;
  235 +
  236 +
  237 +/**
218 238 获取当前SDK的连接状态
219 239  
220 240 @return 当前SDK的连接状态
... ... @@ -223,13 +243,14 @@
223 243  
224 244  
225 245 /**
226   - 获取某个会话中指定数量的最新消息
  246 + 获取某个会话中指定数量的最新消息(私聊有效)
227 247  
228   - @param conversationType 会话类型(私聊 / 聊天室)
229   - @param targetId 会话目标ID(私聊:用户ID / 聊天室:聊天室ID)
  248 + @param conversationType 会话类型(私聊)
  249 + @param targetId 会话目标ID(私聊:用户ID)
230 250 @param count 所要获取的消息数量
231 251  
232   - @return 消息数组(CNLiveChatMessage类型)
  252 + @return 消息数组
  253 + (包括 CNLiveChatMessage文本类型 / CNliveChatImageMessage图片类型 / CNLiveChatVoiceMessage语音类型)
233 254 @discussion
234 255 此方法会获取该会话中指定数量的最新消息实体,返回的消息实体按照时间从新到旧排列。
235 256 如果会话中的消息数量小于参数count的值,会将该会话中的所有消息返回。
... ...
CNLiveChatSDKDemo/CNLiveChatManager.framework/Headers/CNLiveChatMessage.h renamed to CNLiveChatSDKDemo/CNLiveChatSDKDemo/CNLiveChatManager.framework/Headers/CNLiveChatMessage.h
CNLiveChatSDKDemo/CNLiveChatManager.framework/Headers/CNLiveChatStatusDefine.h renamed to CNLiveChatSDKDemo/CNLiveChatSDKDemo/CNLiveChatManager.framework/Headers/CNLiveChatStatusDefine.h
CNLiveChatSDKDemo/CNLiveChatManager.framework/Headers/CNLiveChatUserInfo.h renamed to CNLiveChatSDKDemo/CNLiveChatSDKDemo/CNLiveChatManager.framework/Headers/CNLiveChatUserInfo.h
CNLiveChatSDKDemo/CNLiveChatSDKDemo/CNLiveChatManager.framework/Headers/CNLiveChatVoiceMessage.h 0 → 100644
  1 +//
  2 +// CNLiveChatVoiceMessage.h
  3 +// CNLiveChatManagerSDKDemo
  4 +//
  5 +// Created by cnliveJunBo on 17/7/12.
  6 +// Copyright © 2017年 cnlive. All rights reserved.
  7 +//
  8 +
  9 +#import <Foundation/Foundation.h>
  10 +#import "CNLiveChatStatusDefine.h"
  11 +#import "CNLiveChatUserInfo.h"
  12 +
  13 +@interface CNLiveChatVoiceMessage : NSObject
  14 +
  15 +/*!
  16 + wav格式的音频数据
  17 + */
  18 +@property(nonatomic, strong) NSData *wavAudioData;
  19 +
  20 +/*!
  21 + 语音消息的时长
  22 + */
  23 +@property(nonatomic, assign) long duration;
  24 +
  25 +/*!
  26 + 语音消息的附加信息
  27 + */
  28 +@property(nonatomic, strong) NSString *extra;
  29 +
  30 +// * 基础属性 *
  31 +/**
  32 + 会话类型(私聊 / 聊天室)
  33 + */
  34 +@property (nonatomic, assign) CNLiveConversationType conversationType;
  35 +
  36 +/**
  37 + 目标ID(消息来自聊天室的ID / 接收者ID)
  38 + */
  39 +@property (nonatomic, copy) NSString *targetId;
  40 +
  41 +/**
  42 + 消息ID(本地存储的消息的唯一值(数据库索引唯一值))
  43 + */
  44 +@property (nonatomic, copy) NSString *messageId;
  45 +
  46 +/**
  47 + 发送者的用户信息(userId, name, portraitUri)
  48 + */
  49 +@property (nonatomic, strong) CNLiveChatUserInfo *userInfo;
  50 +
  51 +/*!
  52 + 初始化语音消息
  53 +
  54 + @param audioData wav格式的音频数据
  55 + @param duration 语音消息的时长(单位:秒)
  56 + @return 语音消息对象
  57 +
  58 + @discussion
  59 + 如果您不是使用IMKit中的录音功能,则在初始化语音消息的时候,需要确保以下几点。
  60 + 1. audioData必须是单声道的wav格式音频数据;
  61 + 2. audioData的采样率必须是8000Hz,采样位数(精度)必须为16位。
  62 +
  63 + 您可以参考的录音参数:
  64 + NSDictionary *settings = @{AVFormatIDKey: @(kAudioFormatLinearPCM),
  65 + AVSampleRateKey: @8000.00f,
  66 + AVNumberOfChannelsKey: @1,
  67 + AVLinearPCMBitDepthKey: @16,
  68 + AVLinearPCMIsNonInterleaved: @NO,
  69 + AVLinearPCMIsFloatKey: @NO,
  70 + AVLinearPC'MIsBigEndianKey: @NO};
  71 + */
  72 ++ (instancetype)messageWithAudio:(NSData *)audioData duration:(long)duration;
  73 +
  74 +@end
... ...
CNLiveChatSDKDemo/CNLiveChatManager.framework/Headers/CNLiveCommentCountResult.h renamed to CNLiveChatSDKDemo/CNLiveChatSDKDemo/CNLiveChatManager.framework/Headers/CNLiveCommentCountResult.h
CNLiveChatSDKDemo/CNLiveChatManager.framework/Headers/CNLiveCommentDetailInfoResult.h renamed to CNLiveChatSDKDemo/CNLiveChatSDKDemo/CNLiveChatManager.framework/Headers/CNLiveCommentDetailInfoResult.h
CNLiveChatSDKDemo/CNLiveChatManager.framework/Headers/CNLiveCommentListResult.h renamed to CNLiveChatSDKDemo/CNLiveChatSDKDemo/CNLiveChatManager.framework/Headers/CNLiveCommentListResult.h
CNLiveChatSDKDemo/CNLiveChatManager.framework/Headers/CNLiveCommentManager.h renamed to CNLiveChatSDKDemo/CNLiveChatSDKDemo/CNLiveChatManager.framework/Headers/CNLiveCommentManager.h
CNLiveChatSDKDemo/CNLiveChatSDKDemo/CNLiveChatManager.framework/Headers/CNliveChatImageMessage.h 0 → 100644
  1 +//
  2 +// CNliveChatImageMessage.h
  3 +// CNLiveChatManager
  4 +//
  5 +// Created by cnliveJunBo on 17/7/11.
  6 +// Copyright © 2017年 cnlive. All rights reserved.
  7 +//
  8 +
  9 +#import <Foundation/Foundation.h>
  10 +#import <UIKit/UIKit.h>
  11 +#import "CNLiveChatStatusDefine.h"
  12 +#import "CNLiveChatUserInfo.h"
  13 +
  14 +/*!
  15 + 图片消息类
  16 +
  17 + @discussion 图片消息类
  18 + */
  19 +@interface CNliveChatImageMessage : NSObject
  20 +
  21 +/*!
  22 + 图片消息的URL地址
  23 +
  24 + @discussion 发送方此字段为图片的本地路径,接收方此字段为网络URL地址。
  25 + */
  26 +@property(nonatomic, strong) NSString *imageUrl;
  27 +
  28 +/*!
  29 + 图片消息的缩略图
  30 + */
  31 +@property(nonatomic, strong) UIImage *thumbnailImage;
  32 +
  33 +/*!
  34 + 是否发送原图
  35 +
  36 + @discussion 在发送图片的时候,是否发送原图,默认值为NO。
  37 + */
  38 +@property(nonatomic, getter=isFull) BOOL full;
  39 +
  40 +/*!
  41 + 图片消息的附加信息
  42 + */
  43 +@property(nonatomic, strong) NSString *extra;
  44 +
  45 +/*!
  46 + 图片消息的原始图片信息
  47 + */
  48 +@property(nonatomic, strong) UIImage *originalImage;
  49 +
  50 +// * 基础属性 *
  51 +/**
  52 + 会话类型(私聊 / 聊天室)
  53 + */
  54 +@property (nonatomic, assign) CNLiveConversationType conversationType;
  55 +
  56 +/**
  57 + 目标ID(消息来自聊天室的ID / 接收者ID)
  58 + */
  59 +@property (nonatomic, copy) NSString *targetId;
  60 +
  61 +/**
  62 + 消息ID(本地存储的消息的唯一值(数据库索引唯一值))
  63 + */
  64 +@property (nonatomic, copy) NSString *messageId;
  65 +
  66 +/**
  67 + 发送者的用户信息(userId, name, portraitUri)
  68 + */
  69 +@property (nonatomic, strong) CNLiveChatUserInfo *userInfo;
  70 +
  71 +/*!
  72 + 初始化图片消息
  73 +
  74 + @param image 原始图片
  75 + @return 图片消息对象
  76 + */
  77 +// 发: originalImage thumbnailImage 有值 imageUrl 无值
  78 +// 收: thumbnailImage imageUrl 有值 originalImage 无值
  79 ++ (instancetype)messageWithImage:(UIImage *)image;
  80 +
  81 +/*!
  82 + 初始化图片消息
  83 +
  84 + @param imageURI 图片的本地路径
  85 + @return 图片消息对象
  86 + */
  87 +// 发(本地路径): originalImage thumbnailImage imageUrl 有值
  88 +// 收: originalImage 无值 thumbnailImage imageUrl 有值
  89 ++ (instancetype)messageWithImageURI:(NSString *)imageURI;
  90 +
  91 +@end
... ...
CNLiveChatSDKDemo/CNLiveChatManager.framework/Info.plist renamed to CNLiveChatSDKDemo/CNLiveChatSDKDemo/CNLiveChatManager.framework/Info.plist
No preview for this file type
CNLiveChatSDKDemo/CNLiveChatSDKDemo/CNLiveImageTableViewCell.h 0 → 100644
  1 +//
  2 +// CNLiveImageTableViewCell.h
  3 +// CNLiveChatSDKDemo
  4 +//
  5 +// Created by cnliveJunBo on 17/7/17.
  6 +// Copyright © 2017年 cnlive. All rights reserved.
  7 +//
  8 +
  9 +#import <Foundation/Foundation.h>
  10 +
  11 +@interface CNLiveImageTableViewCell : UITableViewCell
  12 +
  13 +@property (nonatomic, strong) MessageModel *model;
  14 +
  15 +@end
... ...
CNLiveChatSDKDemo/CNLiveChatSDKDemo/CNLiveImageTableViewCell.m 0 → 100644
  1 +//
  2 +// CNLiveImageTableViewCell.m
  3 +// CNLiveChatSDKDemo
  4 +//
  5 +// Created by cnliveJunBo on 17/7/17.
  6 +// Copyright © 2017年 cnlive. All rights reserved.
  7 +//
  8 +
  9 +#import "CNLiveImageTableViewCell.h"
  10 +
  11 +@interface CNLiveImageTableViewCell()
  12 +
  13 +@property (nonatomic, strong) UIImageView *imgView;
  14 +
  15 +@end
  16 +
  17 +@implementation CNLiveImageTableViewCell
  18 +
  19 +- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
  20 +{
  21 + self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
  22 + if (self) {
  23 + [self.contentView addSubview:self.imgView];
  24 + }
  25 + return self;
  26 +}
  27 +
  28 +- (void)setModel:(MessageModel *)model {
  29 + if (_model != model) {
  30 + _model = model;
  31 + }
  32 + [_imgView setImage:model.thumbnailImage]; // 缩略图
  33 +}
  34 +
  35 +- (UIImageView *)imgView {
  36 +
  37 + if (!_imgView) {
  38 + _imgView = [[UIImageView alloc] initWithFrame:CGRectMake(10, 5, 80, 80)];
  39 + _imgView.backgroundColor = [UIColor lightGrayColor];
  40 + }
  41 + return _imgView;
  42 +}
  43 +
  44 +@end
... ...
CNLiveChatSDKDemo/CNLiveMsgTools.framework/CNLiveMsgTools renamed to CNLiveChatSDKDemo/CNLiveChatSDKDemo/CNLiveMsgTools.framework/CNLiveMsgTools
No preview for this file type
CNLiveChatSDKDemo/CNLiveMsgTools.framework/Emoji.plist renamed to CNLiveChatSDKDemo/CNLiveChatSDKDemo/CNLiveMsgTools.framework/Emoji.plist
No preview for this file type
CNLiveChatSDKDemo/CNLiveMsgTools.framework/Headers/CNLiveMsgManager.h renamed to CNLiveChatSDKDemo/CNLiveChatSDKDemo/CNLiveMsgTools.framework/Headers/CNLiveMsgManager.h
... ... @@ -12,6 +12,7 @@
12 12  
13 13 @property (nonatomic, readonly, assign) BOOL isTestEnvironment;
14 14  
  15 +
15 16 + (NSString *)getCNLiveMsgVersion;
16 17  
17 18  
... ... @@ -25,6 +26,12 @@
25 26 - (NSDictionary *)getToolsInfo;
26 27  
27 28  
  29 +- (NSDictionary *)messageWithImage:(id)image;
  30 +
  31 +
  32 +- (NSDictionary *)messageWithVoice:(NSData *)voiceData duration:(long)duration;
  33 +
  34 +
28 35 - (void)initCNLiveMsgToolsWithAppKey:(NSString *)appKey appId:(NSString *)appId;
29 36  
30 37  
... ... @@ -72,13 +79,23 @@
72 79 error:(void (^)(NSInteger errors, NSString *targetId))errorBlock;
73 80  
74 81  
75   -- (void)sendCarrier:(NSString *)carrier
  82 +- (void)sendCarrier:(NSDictionary *)carrier
76 83 type:(NSInteger)type
77 84 targetId:(NSString *)targetId
78 85 success:(void (^)(NSString *carrier, NSString *messageId, NSString *targetId, NSInteger type, NSString *infoId, NSString *infoName, NSString *infoUrl, long long goTime, long long comeTime))successBlock
79 86 error:(void (^)(NSInteger errors, NSString *messageId, NSString *targetId))errorBlock;
80 87  
81 88  
  89 +- (void)sendMedia:(NSDictionary *)media type:(NSInteger)type
  90 + targetId:(NSString *)targetId
  91 + pushContent:(NSString *)pushContent
  92 + pushData:(NSString *)pushData
  93 + progress:(void (^)(int progress, NSString *messageId))progressBlock
  94 + success:(void (^)(NSString *messageId, NSString *targetId, NSInteger type, NSString *infoId, NSString *infoName, NSString *infoUrl))successBlock
  95 + error:(void (^)(NSInteger errorCode, NSString *messageId))errorBlock
  96 + cancel:(void (^)(NSString * messageId))cancelBlock;
  97 +
  98 +
82 99 - (NSInteger)getOnLineStatus;
83 100  
84 101  
... ...
CNLiveChatSDKDemo/CNLiveMsgTools.framework/Info.plist renamed to CNLiveChatSDKDemo/CNLiveChatSDKDemo/CNLiveMsgTools.framework/Info.plist
No preview for this file type
CNLiveChatSDKDemo/CNLiveMsgTools.framework/RCConfig.plist renamed to CNLiveChatSDKDemo/CNLiveChatSDKDemo/CNLiveMsgTools.framework/RCConfig.plist
No preview for this file type
CNLiveChatSDKDemo/CNLiveMsgTools.framework/en.lproj/RongCloudKit.strings renamed to CNLiveChatSDKDemo/CNLiveChatSDKDemo/CNLiveMsgTools.framework/en.lproj/RongCloudKit.strings
No preview for this file type
CNLiveChatSDKDemo/CNLiveMsgTools.framework/release_notes_ios.txt renamed to CNLiveChatSDKDemo/CNLiveChatSDKDemo/CNLiveMsgTools.framework/release_notes_ios.txt
CNLiveChatSDKDemo/CNLiveMsgTools.framework/zh-Hans.lproj/RongCloudKit.strings renamed to CNLiveChatSDKDemo/CNLiveChatSDKDemo/CNLiveMsgTools.framework/zh-Hans.lproj/RongCloudKit.strings
No preview for this file type
CNLiveChatSDKDemo/CNLiveChatSDKDemo/CNLiveVoiceTableViewCell.h 0 → 100644
  1 +//
  2 +// CNLiveVoiceTableViewCell.h
  3 +// CNLiveChatSDKDemo
  4 +//
  5 +// Created by cnliveJunBo on 17/7/17.
  6 +// Copyright © 2017年 cnlive. All rights reserved.
  7 +//
  8 +
  9 +#import <Foundation/Foundation.h>
  10 +
  11 +@interface CNLiveVoiceTableViewCell : UITableViewCell
  12 +
  13 +@property (nonatomic, strong) MessageModel *model;
  14 +
  15 +@end
... ...
CNLiveChatSDKDemo/CNLiveChatSDKDemo/CNLiveVoiceTableViewCell.m 0 → 100644
  1 +//
  2 +// CNLiveVoiceTableViewCell.m
  3 +// CNLiveChatSDKDemo
  4 +//
  5 +// Created by cnliveJunBo on 17/7/17.
  6 +// Copyright © 2017年 cnlive. All rights reserved.
  7 +//
  8 +
  9 +#import "CNLiveVoiceTableViewCell.h"
  10 +
  11 +@interface CNLiveVoiceTableViewCell()<AVAudioPlayerDelegate> {
  12 +
  13 + BOOL _isPlaying;
  14 + NSTimer *_voiceTimer;
  15 + long _voiceTime;
  16 +}
  17 +
  18 +@property (nonatomic, strong) UIButton *voicePlayBtn;
  19 +
  20 +@property (nonatomic, strong) UILabel *timeLabel;
  21 +
  22 +@property (nonatomic, strong) AVAudioPlayer *player;
  23 +
  24 +@end
  25 +
  26 +@implementation CNLiveVoiceTableViewCell
  27 +
  28 +- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
  29 +{
  30 + self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
  31 + if (self) {
  32 + [self.contentView addSubview:self.voicePlayBtn];
  33 + }
  34 + return self;
  35 +}
  36 +
  37 +- (void)setModel:(MessageModel *)model {
  38 + if (_model != model) {
  39 + _model = model;
  40 + }
  41 + _voiceTime = model.duration;
  42 +}
  43 +
  44 +- (void)timeCountDown {
  45 +
  46 + if (_voiceTime > 0) {
  47 + _voiceTime = _voiceTime - 1;
  48 + NSLog(@"%ld",_voiceTime);
  49 + self.timeLabel.text = [NSString stringWithFormat:@"%ld s",_voiceTime];
  50 + } else {
  51 + [_player stop];
  52 + _player = nil;
  53 + _isPlaying = NO;
  54 + [_voiceTimer invalidate];
  55 + _voiceTimer = nil;
  56 + [self.voicePlayBtn setImage:[UIImage imageNamed:@"语音播放"] forState:UIControlStateNormal];
  57 + [self.timeLabel removeFromSuperview];
  58 + _voiceTime = _model.duration;
  59 + }
  60 +}
  61 +
  62 +- (void)voicePlay {
  63 +
  64 + if (_isPlaying) {
  65 + [_player stop];
  66 + _player = nil;
  67 + [self.voicePlayBtn setImage:[UIImage imageNamed:@"语音播放"] forState:UIControlStateNormal];
  68 + } else {
  69 + [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:nil];
  70 + NSError *error=nil;
  71 + _player = [[AVAudioPlayer alloc] initWithData:_model.wavAudioData error:&error];
  72 + _player.delegate = self;
  73 + _player.numberOfLoops = 0;
  74 + [_player prepareToPlay];
  75 + if (error) {
  76 + NSLog(@"初始化播放器过程发生错误,错误信息:%@",error.localizedDescription);
  77 + }
  78 + [_player play];
  79 + [self.voicePlayBtn setImage:[UIImage imageNamed:@"语音播"] forState:UIControlStateNormal];
  80 + [self.contentView addSubview:self.timeLabel];
  81 + self.timeLabel.text = [NSString stringWithFormat:@"%ld s",_voiceTime];
  82 + _voiceTimer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(timeCountDown) userInfo:nil repeats:YES];
  83 + }
  84 + _isPlaying = !_isPlaying;
  85 +}
  86 +
  87 +- (UIButton *)voicePlayBtn {
  88 + if (!_voicePlayBtn) {
  89 + _voicePlayBtn = [UIButton buttonWithType:UIButtonTypeCustom];
  90 + [_voicePlayBtn setFrame:CGRectMake(10, 5, 100, 40)];
  91 + [_voicePlayBtn setImage:[UIImage imageNamed:@"语音播放"] forState:UIControlStateNormal];
  92 + _voicePlayBtn.backgroundColor = [UIColor lightGrayColor];
  93 + [_voicePlayBtn addTarget:self action:@selector(voicePlay) forControlEvents:UIControlEventTouchUpInside];
  94 + }
  95 + return _voicePlayBtn;
  96 +}
  97 +
  98 +- (UILabel *)timeLabel {
  99 + if (!_timeLabel) {
  100 + _timeLabel = [[UILabel alloc] initWithFrame:CGRectMake(110, 5, 50, 40)];
  101 + _timeLabel.backgroundColor = [UIColor lightGrayColor];
  102 + [_timeLabel setTextColor:[UIColor whiteColor]];
  103 + }
  104 + return _timeLabel;
  105 +}
  106 +
  107 +@end
... ...
CNLiveChatSDKDemo/CNLiveChatSDKDemo/ChatRoomViewController.m
... ... @@ -8,20 +8,38 @@
8 8  
9 9 #import "ChatRoomViewController.h"
10 10  
11   -static NSString *cellId = @"cellId";
  11 +static NSString *textCellId = @"textCellId";
  12 +static NSString *voiceCellId = @"voiceCellId";
  13 +static NSString *imageCellId = @"imageCellId";
  14 +
  15 +#define chatRoomId @"67_78734255"
12 16  
13 17 @interface ChatRoomViewController ()<UITextFieldDelegate, CNLiveChatManagerDelegate, UITableViewDelegate, UITableViewDataSource> {
14 18  
15 19 NSMutableArray *_messageArrayM;
16   - NSString *_messageSelf;
  20 + BOOL _isVoice;
  21 + NSTimer *_getCountTimer;
17 22 }
18 23  
  24 +@property (nonatomic, strong) UIView *textViewBackView;
  25 +
19 26 @property (nonatomic, strong) UITextField *textField;
20 27  
21 28 @property (nonatomic, strong) UILabel *chatRoomPersonCountLabel;
22 29  
23 30 @property (nonatomic, strong) UITableView *tableView;
24 31  
  32 +@property (nonatomic, strong) UIButton *imgButton;
  33 +
  34 +@property (nonatomic, strong) UIButton *voiceButton;
  35 +
  36 +@property (nonatomic, strong) UIButton *voiceSendBtn;
  37 +
  38 +@property (nonatomic, strong) AVAudioRecorder *recorder;// 录音
  39 +@property (nonatomic, strong) NSURL *recordTempFileURL; // 录音临时地址
  40 +@property (nonatomic, strong) NSData *recordedData; // 录音数据
  41 +@property (nonatomic, assign) NSTimeInterval duration; // 录音时长
  42 +
25 43 @end
26 44  
27 45 @implementation ChatRoomViewController
... ... @@ -30,26 +48,23 @@ static NSString *cellId = @&quot;cellId&quot;;
30 48 [super viewDidLoad];
31 49  
32 50 self.view.backgroundColor = [UIColor whiteColor];
33   -
34 51 self.title = @"聊天室";
35   -
  52 + [self addNotification];
36 53 self.automaticallyAdjustsScrollViewInsets = NO;
37 54  
38 55 [CNLiveChatManager sharedCNLiveChatManager].delegate = self;
39 56  
40   - [[CNLiveChatManager sharedCNLiveChatManager] joinChatRoom:@"67_7788" messageCount:10 success:^(NSString *targetId) {
  57 + [[CNLiveChatManager sharedCNLiveChatManager] joinChatRoom:chatRoomId messageCount:10 success:^(NSString *targetId) {
41 58  
42 59 NSLog(@"已成功加入聊天室:%@",targetId);
43   - [self getChatRoomPersonCount];
44 60  
  61 + [self getChatRoomPersonCount]; // 获取聊天室人数
45 62 dispatch_async(dispatch_get_global_queue(0, 0), ^{
46   - [NSTimer scheduledTimerWithTimeInterval:5 target:self selector:@selector(getChatRoomPersonCount) userInfo:nil repeats:YES];
  63 + _getCountTimer = [NSTimer scheduledTimerWithTimeInterval:5 target:self selector:@selector(getChatRoomPersonCount) userInfo:nil repeats:YES];
47 64 [[NSRunLoop currentRunLoop] run];
48 65 });
49 66  
50   -
51 67 } error:^(CNLiveChatErrorCode errors, NSString *targetId) {
52   -
53 68 NSLog(@"加入聊天室:%@失败,错误码:%ld",targetId,(long)errors);
54 69 }];
55 70  
... ... @@ -57,8 +72,8 @@ static NSString *cellId = @&quot;cellId&quot;;
57 72 UITapGestureRecognizer *gestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(hideKeyboard)];
58 73 gestureRecognizer.cancelsTouchesInView = YES;
59 74 [self.tableView addGestureRecognizer:gestureRecognizer];
60   - [self.view addSubview:self.textField];
61 75 [self.view addSubview:self.chatRoomPersonCountLabel];
  76 + [self.view addSubview:self.textViewBackView];
62 77  
63 78 _messageArrayM = [[NSMutableArray alloc] init];
64 79 }
... ... @@ -67,7 +82,10 @@ static NSString *cellId = @&quot;cellId&quot;;
67 82  
68 83 [super viewWillDisappear:animated];
69 84  
70   - [[CNLiveChatManager sharedCNLiveChatManager] quitChatRoom:@"67_7788" success:^(NSString *targetId) {
  85 + [_getCountTimer invalidate];
  86 + _getCountTimer = nil;
  87 +
  88 + [[CNLiveChatManager sharedCNLiveChatManager] quitChatRoom:chatRoomId success:^(NSString *targetId) {
71 89 NSLog(@"退出聊天室:%@成功",targetId);
72 90 } error:^(CNLiveChatErrorCode errors, NSString *targetId) {
73 91 NSLog(@"退出聊天室:%@失败,错误码:%ld",targetId,(long)errors);
... ... @@ -78,15 +96,13 @@ static NSString *cellId = @&quot;cellId&quot;;
78 96 #pragma mark - 获取聊天室人数
79 97 - (void)getChatRoomPersonCount {
80 98  
81   - [[CNLiveChatManager sharedCNLiveChatManager] getChatRoomInfo:@"67_7788" success:^(int totalMemberCount) {
  99 + [[CNLiveChatManager sharedCNLiveChatManager] getChatRoomInfo:chatRoomId success:^(int totalMemberCount) {
82 100  
83   - NSLog(@"success: %d",totalMemberCount);
84 101 dispatch_async(dispatch_get_main_queue(), ^{
85 102 self.chatRoomPersonCountLabel.text = [NSString stringWithFormat:@"聊天室人数为:%d",totalMemberCount];
86 103 });
87 104  
88 105 } error:^(CNLiveChatErrorCode status) {
89   -
90 106 NSLog(@"failed");
91 107 }];
92 108 }
... ... @@ -94,107 +110,147 @@ static NSString *cellId = @&quot;cellId&quot;;
94 110  
95 111 #pragma mark - UITableViewDelegate,UITableViewDataSource !!!!!!!!!!!!!!!!!!!!!!!!!!
96 112  
97   -- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
98   - return 1;
99   -}
100   -
101 113 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
102 114 return _messageArrayM.count;
103 115 }
104 116  
105   -- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
106   -
107   - UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellId forIndexPath:indexPath];
  117 +- (id)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
108 118  
109 119 MessageModel *model = _messageArrayM[indexPath.row];
110 120  
111   - NSMutableAttributedString *AttributedStr = [[NSMutableAttributedString alloc]initWithString:[NSString stringWithFormat:@"%@: %@",model.name,model.message]];
112   -
113   - if ([model.userId isEqualToString:[CNLiveChatManager sharedCNLiveChatManager].currentUserInfo.userId]) {
  121 + if (model.message) { // 文本消息
  122 + UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:textCellId forIndexPath:indexPath];
  123 + NSMutableAttributedString *AttributedStr = [[NSMutableAttributedString alloc]initWithString:[NSString stringWithFormat:@"%@: %@",model.name,model.message]];
114 124  
115   - [AttributedStr addAttribute:NSForegroundColorAttributeName
116   -
117   - value:[UIColor redColor]
118   -
119   - range:NSMakeRange(0, model.name.length)];
  125 + if ([model.userId isEqualToString:[CNLiveChatManager sharedCNLiveChatManager].currentUserInfo.userId]) {
  126 + [AttributedStr addAttribute:NSForegroundColorAttributeName
  127 + value:[UIColor redColor]
  128 + range:NSMakeRange(0, model.name.length)];
  129 + cell.textLabel.attributedText = AttributedStr;
  130 + } else {
  131 + [AttributedStr addAttribute:NSForegroundColorAttributeName
  132 + value:[UIColor blackColor]
  133 + range:NSMakeRange(0, model.name.length)];
  134 + cell.textLabel.attributedText = AttributedStr;
  135 + }
  136 + return cell;
120 137  
121   - cell.textLabel.attributedText = AttributedStr;
122   - } else {
  138 + } else if (model.wavAudioData) { // 语音消息
123 139  
124   - [AttributedStr addAttribute:NSForegroundColorAttributeName
125   -
126   - value:[UIColor blackColor]
127   -
128   - range:NSMakeRange(0, model.name.length)];
  140 + CNLiveVoiceTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:voiceCellId forIndexPath:indexPath];
  141 + cell.model = model;
  142 + return cell;
  143 + } else if (model.wavAudioData || model.thumbnailImage) {
129 144  
130   - cell.textLabel.attributedText = AttributedStr;
  145 + CNLiveImageTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:imageCellId forIndexPath:indexPath];
  146 + cell.model = model;
  147 + return cell;
131 148 }
132   -
133   - return cell;
  149 + return nil;
134 150 }
135 151  
  152 +- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
  153 +
  154 + MessageModel *model = _messageArrayM[indexPath.row];
  155 + if (model.wavAudioData) {
  156 + return 50;
  157 + } else if (model.imageUrl || model.thumbnailImage) {
  158 + return 100;
  159 + }
  160 + return 30;
  161 +}
136 162  
137 163 #pragma mark - UITextFieldDelegate !!!!!!!!!!!!!!!!!!!!!!!!!!
138 164 - (BOOL)textFieldShouldReturn:(UITextField *)textField { // 发送消息
139 165  
140   - [[CNLiveChatManager sharedCNLiveChatManager] sendMessage:textField.text type:CNLive_ConversationType_CHATROOM targetId:@"67_7788" success:^(CNLiveChatMessage *message) {
  166 + [[CNLiveChatManager sharedCNLiveChatManager] sendMessage:textField.text type:CNLive_ConversationType_CHATROOM targetId:chatRoomId success:^(id message) {
141 167  
142   - NSLog(@"发送消息成功:%@",message.messageId);
143 168 // 自己发送的消息不会被onReceived:方法实时监听,需要自己做处理
144   - MessageModel *model = [[MessageModel alloc] init];
145   -
146   - model.message = _messageSelf;
147   - CNLiveChatUserInfo *userInfo = [CNLiveChatManager sharedCNLiveChatManager].currentUserInfo;
148   - model.userId = userInfo.userId;
149   - model.name = userInfo.name;
150   - model.portraitUri = userInfo.portraitUri;
151   - model.type = CNLive_ConversationType_CHATROOM;
152   - model.messageId = message.messageId;
153   -
154   - [_messageArrayM addObject:model];
155   -
156   - // 此处更新 UI 应到主线程
157   - dispatch_async(dispatch_get_main_queue(), ^{
  169 + if ([message isKindOfClass:[CNLiveChatMessage class]]) {
158 170  
159   - [self.tableView reloadData];
  171 + CNLiveChatMessage *textMsg = message;
  172 + NSLog(@"文本消息发送成功:%@",textMsg.messageContent);
  173 + MessageModel *model = [[MessageModel alloc] init];
  174 + model.message = textMsg.messageContent;
  175 + model.userId = textMsg.userInfo.userId;
  176 + model.name = textMsg.userInfo.name;
  177 + model.portraitUri = textMsg.userInfo.portraitUri;
  178 + model.type = textMsg.conversationType;
  179 + model.messageId = textMsg.messageId;
  180 + [_messageArrayM addObject:model];
160 181  
161   - [self scrollToBottom];
162   - });
  182 + // 此处更新 UI 应到主线程
  183 + dispatch_async(dispatch_get_main_queue(), ^{
  184 + [self.tableView reloadData];
  185 + [self scrollToBottom];
  186 + });
  187 + }
163 188  
164 189 } error:^(CNLiveChatErrorCode errors, NSString *messageId, NSString *targetId) {
165   -
166   - NSLog(@"向聊天室:%@发送消息失败,错误代码:%ld,信息ID:%@",targetId,(long)errors,messageId);
  190 + NSLog(@"向聊天室:%@发送文本消息失败,错误代码:%ld,信息ID:%@",targetId,(long)errors,messageId);
167 191 }];
168 192  
169   - _messageSelf = textField.text;
170 193 textField.text = @"";
171   -
172 194 return YES;
173 195 }
174 196  
175 197  
176 198 #pragma mark - CNLiveChatManagerDelegate !!!!!!!!!!!!!!!!!!!!!!!!!!
177   -- (void)onReceived:(CNLiveChatMessage *)message {
178   -
179   - NSLog(@"收到消息类型:%lu,消息ID:%@,消息内容:%@,消息发送者信息:%@,消息ID:%@",(unsigned long)message.conversationType,message.targetId,message.messageContent,message.userInfo,message.messageId);
  199 +- (void)onReceived:(id)message {
180 200  
181   - // 只显示本聊天室信息
182   - if (message.conversationType == CNLive_ConversationType_CHATROOM && [message.targetId isEqualToString:@"67_7788"]) {
  201 + if ([message isKindOfClass:[CNLiveChatMessage class]]) {
183 202  
184   - MessageModel *model = [[MessageModel alloc] init];
  203 + CNLiveChatMessage * msg = (CNLiveChatMessage *)message;
  204 + // 只显示本聊天室信息
  205 + if (msg.conversationType == CNLive_ConversationType_CHATROOM && [msg.targetId isEqualToString:chatRoomId]) {
  206 +
  207 + MessageModel *model = [[MessageModel alloc] init];
  208 + model.message = msg.messageContent;
  209 + model.userId = msg.userInfo.userId;
  210 + model.name = msg.userInfo.name;
  211 + model.portraitUri = msg.userInfo.portraitUri;
  212 + model.type = msg.conversationType;
  213 + [_messageArrayM addObject:model];
  214 + }
  215 + } else if ([message isKindOfClass:[CNliveChatImageMessage class]]) {
185 216  
186   - model.message = message.messageContent;
187   - model.userId = message.userInfo.userId;
188   - model.name = message.userInfo.name;
189   - model.portraitUri = message.userInfo.portraitUri;
190   - model.type = message.conversationType;
  217 + CNliveChatImageMessage * msg = (CNliveChatImageMessage *)message;
191 218  
192   - [_messageArrayM addObject:model];
  219 + if (msg.conversationType == CNLive_ConversationType_CHATROOM && [msg.targetId isEqualToString:chatRoomId]) {
  220 +
  221 + MessageModel *model = [[MessageModel alloc] init];
  222 + model.imageUrl = msg.imageUrl;
  223 + model.thumbnailImage = msg.thumbnailImage;
  224 + model.isFull = msg.isFull;
  225 + model.originalImage = msg.originalImage;
  226 + model.extra = msg.extra;
  227 + model.userId = msg.userInfo.userId;
  228 + model.name = msg.userInfo.name;
  229 + model.portraitUri = msg.userInfo.portraitUri;
  230 + model.type = msg.conversationType;
  231 + [_messageArrayM addObject:model];
  232 + }
  233 +
  234 + } else if ([message isKindOfClass:[CNLiveChatVoiceMessage class]]) {
193 235  
194   - [self.tableView reloadData];
  236 + CNLiveChatVoiceMessage * msg = (CNLiveChatVoiceMessage *)message;
195 237  
196   - [self scrollToBottom];
  238 + if (msg.conversationType == CNLive_ConversationType_CHATROOM && [msg.targetId isEqualToString:chatRoomId]) {
  239 +
  240 + MessageModel *model = [[MessageModel alloc] init];
  241 + model.wavAudioData = msg.wavAudioData;
  242 + model.duration = msg.duration;
  243 + model.extra = msg.extra; // 扩展
  244 + model.targetId = msg.targetId;
  245 + model.userId = msg.userInfo.userId;
  246 + model.name = msg.userInfo.name;
  247 + model.portraitUri = msg.userInfo.portraitUri;
  248 + model.type = msg.conversationType;
  249 + [_messageArrayM addObject:model];
  250 + }
197 251 }
  252 + [self.tableView reloadData];
  253 + [self scrollToBottom];
198 254 }
199 255  
200 256 - (void)onConnectionStatusChanged:(CNLiveConnectionStatus)status {
... ... @@ -221,12 +277,130 @@ static NSString *cellId = @&quot;cellId&quot;;
221 277 NSLog(@"账号%@在其他设备登陆",userId);
222 278 }
223 279  
  280 +#pragma mark - 图片 Button Action !!!!!!!!!!!!!!!!!!!!!!!!
  281 +- (void)sendImage {
  282 +
  283 + NSString *path = [[NSBundle mainBundle] pathForResource:@"tu.jpg" ofType:nil];
  284 + CNliveChatImageMessage *imageMsg = [CNliveChatImageMessage messageWithImageURI:path];
  285 +
  286 + [[CNLiveChatManager sharedCNLiveChatManager] sendMediaMessage:CNLive_ConversationType_CHATROOM targetId:chatRoomId content:imageMsg progress:^(int progress, NSString *messageId) {
  287 + NSLog(@"发送进度");
  288 + } success:^(CNliveChatImageMessage *message) {
  289 +
  290 + NSLog(@"图片消息发送成功~");
  291 + MessageModel *model = [[MessageModel alloc] init];
  292 + model.imageUrl = message.imageUrl;
  293 + model.thumbnailImage = message.thumbnailImage;
  294 + model.isFull = message.isFull;
  295 + model.originalImage = message.originalImage;
  296 + model.extra = message.extra;
  297 + model.userId = message.userInfo.userId;
  298 + model.name = message.userInfo.name;
  299 + model.portraitUri = message.userInfo.portraitUri;
  300 + model.type = message.conversationType;
  301 + model.messageId = message.messageId;
  302 + [_messageArrayM addObject:model];
  303 +
  304 + // 此处更新 UI 应到主线程
  305 + dispatch_async(dispatch_get_main_queue(), ^{
  306 + [self.tableView reloadData];
  307 + [self scrollToBottom];
  308 + });
  309 +
  310 + } error:^(CNLiveChatErrorCode errorCode, NSString *messageId) {
  311 + NSLog(@"发送图片消息失败,错误码:%ld",(long)errorCode);
  312 + }];
  313 +}
  314 +
  315 +#pragma mark - 语音 Button Action !!!!!!!!!!!!!!!!!!!!!!!!
  316 +- (void)voiceAction {
  317 +
  318 + _isVoice = !_isVoice;
  319 + if (_isVoice) {
  320 + [self.textField removeFromSuperview];
  321 + [self.textViewBackView addSubview:self.voiceSendBtn];
  322 + } else {
  323 + [self.voiceSendBtn removeFromSuperview];
  324 + [self.textViewBackView addSubview:self.textField];
  325 + }
  326 +}
  327 +
  328 +- (void)startRecord {
  329 + NSLog(@"讲话");
  330 +
  331 + [self.recorder prepareToRecord];
  332 +
  333 + [self.recorder record];
  334 +}
  335 +
  336 +- (void)stopRecord {
  337 + NSLog(@"松手");
  338 +
  339 + if (self.recorder.isRecording) {
  340 + self.recordedData =[NSData dataWithContentsOfURL:self.recordTempFileURL];
  341 + self.duration = self.recorder.currentTime;
  342 + [self.recorder stop];
  343 + self.recorder = nil;
  344 + }
  345 +
  346 + if (self.recordedData && self.duration > 1) {
  347 +
  348 + CNLiveChatVoiceMessage *voiceMsg = [CNLiveChatVoiceMessage messageWithAudio:self.recordedData duration:self.duration];
  349 +
  350 + [[CNLiveChatManager sharedCNLiveChatManager] sendMessage:voiceMsg type:CNLive_ConversationType_CHATROOM targetId:chatRoomId success:^(id message) {
  351 +
  352 + NSLog(@"语音消息发送成功");
  353 + // 自己发送的消息不会被onReceived:方法实时监听,需要自己做处理
  354 + if ([message isKindOfClass:[CNLiveChatVoiceMessage class]]) {
  355 +
  356 + CNLiveChatVoiceMessage *voiceMsg = message;
  357 + MessageModel *model = [[MessageModel alloc] init];
  358 +
  359 + model.wavAudioData = voiceMsg.wavAudioData;
  360 + model.duration = voiceMsg.duration;
  361 + model.extra = voiceMsg.extra; // 扩展
  362 + model.targetId = voiceMsg.targetId;
  363 + CNLiveChatUserInfo *userInfo = [CNLiveChatManager sharedCNLiveChatManager].currentUserInfo;
  364 + model.userId = userInfo.userId;
  365 + model.name = userInfo.name;
  366 + model.portraitUri = userInfo.portraitUri;
  367 + model.type = CNLive_ConversationType_CHATROOM;
  368 +
  369 + [_messageArrayM addObject:model];
  370 +
  371 + // 此处更新 UI 应到主线程
  372 + dispatch_async(dispatch_get_main_queue(), ^{
  373 +
  374 + [self.tableView reloadData];
  375 +
  376 + [self scrollToBottom];
  377 + });
  378 + }
  379 +
  380 + } error:^(CNLiveChatErrorCode errors, NSString *messageId, NSString *targetId) {
  381 + NSLog(@"语音发送失败,错误码:%ld",errors);
  382 + }];
  383 + } else {
  384 + NSLog(@"时间太短,重新录制");
  385 + }
  386 +}
  387 +
  388 +#pragma mark - Get Method !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  389 +- (UIView *)textViewBackView {
  390 + if (!_textViewBackView) {
  391 + _textViewBackView = [[UIView alloc] initWithFrame:CGRectMake(0, KScreenHeight-50, KScreenWidth, 50)];
  392 + _textViewBackView.backgroundColor = [UIColor colorWithRed:(230.0/255.0) green:(230.0/255.0) blue:(230.0/255.0) alpha:1];
  393 + [_textViewBackView addSubview:self.textField];
  394 + [_textViewBackView addSubview:self.voiceButton];
  395 + [_textViewBackView addSubview:self.imgButton];
  396 + }
  397 + return _textViewBackView;
  398 +}
224 399  
225   -#pragma mark - Get Method !!!!!!!!!!!!!!!!!!!!!!!!!!
226 400 - (UITextField *)textField {
227 401  
228 402 if (!_textField) {
229   - _textField = [self createTextFieldWithFrame:CGRectMake(10, 74, KScreenWidth - 20, 40) font:20];
  403 + _textField = [self createTextFieldWithFrame:CGRectMake(43, 5, KScreenWidth - 86, 40) font:20];
230 404 _textField.delegate = self;
231 405 }
232 406 return _textField;
... ... @@ -235,22 +409,82 @@ static NSString *cellId = @&quot;cellId&quot;;
235 409 - (UILabel *)chatRoomPersonCountLabel {
236 410  
237 411 if (!_chatRoomPersonCountLabel) {
238   - _chatRoomPersonCountLabel = [[UILabel alloc] initWithFrame:CGRectMake(10, 124, KScreenWidth - 20, 35)];
  412 + _chatRoomPersonCountLabel = [[UILabel alloc] initWithFrame:CGRectMake(10, 64, KScreenWidth - 20, 35)];
239 413 }
240 414 return _chatRoomPersonCountLabel;
241 415 }
242 416  
243 417 -(UITableView *)tableView {
244 418 if (!_tableView) {
245   - _tableView = [[UITableView alloc] initWithFrame:CGRectMake(0, 159, KScreenWidth, KScreenHeight - 425) style:UITableViewStylePlain];
  419 + _tableView = [[UITableView alloc] initWithFrame:CGRectMake(0, 97, KScreenWidth, KScreenHeight - 147) style:UITableViewStylePlain];
246 420 _tableView.rowHeight = 30;
247 421 _tableView.delegate = self;
248 422 _tableView.dataSource = self;
249   - [_tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:cellId];
  423 + [_tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:textCellId];
  424 + [_tableView registerClass:[CNLiveVoiceTableViewCell class] forCellReuseIdentifier:voiceCellId];
  425 + [_tableView registerClass:[CNLiveImageTableViewCell class] forCellReuseIdentifier:imageCellId];
250 426 }
251 427 return _tableView;
252 428 }
253 429  
  430 +- (UIButton *)imgButton {
  431 + if (!_imgButton) {
  432 + _imgButton = [UIButton buttonWithType:UIButtonTypeCustom];
  433 + _imgButton.frame = CGRectMake(KScreenWidth - 40, 5, 40, 40);
  434 + [_imgButton setImage:[UIImage imageNamed:@"加号"] forState:UIControlStateNormal];
  435 + [_imgButton addTarget:self action:@selector(sendImage) forControlEvents:UIControlEventTouchUpInside];
  436 + }
  437 + return _imgButton;
  438 +}
  439 +
  440 +- (UIButton *)voiceButton {
  441 + if (!_voiceButton) {
  442 + _voiceButton = [UIButton buttonWithType:UIButtonTypeCustom];
  443 + _voiceButton.frame = CGRectMake(0, 5, 40, 40);
  444 + [_voiceButton setImage:[UIImage imageNamed:@"语音"] forState:UIControlStateNormal];
  445 + [_voiceButton addTarget:self action:@selector(voiceAction) forControlEvents:UIControlEventTouchUpInside];
  446 + }
  447 + return _voiceButton;
  448 +}
  449 +
  450 +- (UIButton *)voiceSendBtn {
  451 + if (!_voiceSendBtn) {
  452 + _voiceSendBtn = [UIButton buttonWithType:UIButtonTypeCustom];
  453 + _voiceSendBtn.frame = CGRectMake(43, 5, KScreenWidth - 86, 40);
  454 + [_voiceSendBtn setTitle:@"按住 说话" forState:UIControlStateNormal];
  455 + [_voiceSendBtn setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
  456 + [_voiceSendBtn setTitle:@"松手 发送" forState:UIControlStateHighlighted];
  457 + [_voiceSendBtn setTitleColor:[UIColor blackColor] forState:UIControlStateHighlighted];
  458 + _voiceSendBtn.backgroundColor = [UIColor whiteColor];
  459 + [_voiceSendBtn addTarget:self action:@selector(startRecord) forControlEvents:UIControlEventTouchDown];
  460 + [_voiceSendBtn addTarget:self action:@selector(stopRecord) forControlEvents:UIControlEventTouchUpInside];
  461 + }
  462 + return _voiceSendBtn;
  463 +}
  464 +
  465 +- (AVAudioRecorder *)recorder { // 录音
  466 + if (!_recorder) {
  467 + NSDictionary *settings = @{AVFormatIDKey: @(kAudioFormatLinearPCM),
  468 + AVSampleRateKey: @8000.00f,
  469 + AVNumberOfChannelsKey: @1,
  470 + AVLinearPCMBitDepthKey: @16,
  471 + AVLinearPCMIsNonInterleaved: @NO,
  472 + AVLinearPCMIsFloatKey: @NO,
  473 + AVLinearPCMIsBigEndianKey: @NO};
  474 + NSError *error;
  475 + [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryRecord error:nil];
  476 + _recorder = [[AVAudioRecorder alloc] initWithURL:self.recordTempFileURL settings:settings error:&error];
  477 + }
  478 + return _recorder;
  479 +}
  480 +
  481 +- (NSURL *)recordTempFileURL {
  482 + if (!_recordTempFileURL) {
  483 + _recordTempFileURL = [NSURL fileURLWithPath:[NSTemporaryDirectory() stringByAppendingPathComponent: @"tempAC.caf"]];
  484 + }
  485 + return _recordTempFileURL;
  486 +}
  487 +
254 488  
255 489 #pragma mark - 创建文本框 !!!!!!!!!!!!!!!!!!!!!!!!!!
256 490 - (UITextField *)createTextFieldWithFrame:(CGRect)frame font:(float)font {
... ... @@ -276,6 +510,72 @@ static NSString *cellId = @&quot;cellId&quot;;
276 510 }
277 511 }
278 512  
  513 +- (void)addNotification {
  514 + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
  515 + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];
  516 +}
  517 +
  518 +#pragma mark <KeyboardNotificationAction> !!!!!!!!!!!!!!!!!!!!!!!!!!!
  519 +- (void)keyboardWillShow:(NSNotification *)notification {
  520 +
  521 + CGRect keyboardRect = [[notification.userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];
  522 + UIViewAnimationCurve curve = [[notification.userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey] integerValue];
  523 + double duration = [[notification.userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];
  524 +
  525 + UIEdgeInsets contentInsets = UIEdgeInsetsMake(0.0,0.0,keyboardRect.size.height,0.0);
  526 + _tableView.contentInset = contentInsets;
  527 + [self scrollToBottom];
  528 +
  529 + [UIView animateWithDuration:duration
  530 + delay:0.0f
  531 + options:[self animationOptionsForCurve:curve]
  532 + animations:^{
  533 +
  534 + CGRect inputViewFrame = self.textViewBackView.frame;
  535 + if (keyboardRect.origin.y == KScreenHeight) {
  536 + self.textViewBackView.frame = CGRectMake(inputViewFrame.origin.x,
  537 + self.view.frame.size.height-(inputViewFrame.size.height),
  538 + inputViewFrame.size.width,
  539 + inputViewFrame.size.height);
  540 + } else {
  541 +
  542 + self.textViewBackView.frame = CGRectMake(inputViewFrame.origin.x,
  543 + self.view.frame.size.height-keyboardRect.size.height-_textViewBackView.frame.size.height,
  544 + inputViewFrame.size.width,
  545 + inputViewFrame.size.height);
  546 +
  547 + }
  548 + }
  549 + completion:^(BOOL finished) {
  550 + }];
  551 +}
  552 +
  553 +- (void)keyboardWillHide:(NSNotification *)notification
  554 +{
  555 + [self.textViewBackView setFrame:CGRectMake(0, KScreenHeight-50, KScreenWidth, self.textViewBackView.frame.size.height)];
  556 + _tableView.contentInset = UIEdgeInsetsZero;
  557 +}
  558 +
  559 +- (UIViewAnimationOptions)animationOptionsForCurve:(UIViewAnimationCurve)curve
  560 +{
  561 + switch (curve) {
  562 + case UIViewAnimationCurveEaseInOut:
  563 + return UIViewAnimationOptionCurveEaseInOut;
  564 + break;
  565 + case UIViewAnimationCurveEaseIn:
  566 + return UIViewAnimationOptionCurveEaseIn;
  567 + break;
  568 + case UIViewAnimationCurveEaseOut:
  569 + return UIViewAnimationOptionCurveEaseOut;
  570 + break;
  571 + case UIViewAnimationCurveLinear:
  572 + return UIViewAnimationOptionCurveLinear;
  573 + break;
  574 + }
  575 +
  576 + return kNilOptions;
  577 +}
  578 +
279 579 #pragma mark - 隐藏键盘 !!!!!!!!!!!!!!!!!!!!!!!
280 580 - (void)hideKeyboard {
281 581  
... ... @@ -287,5 +587,4 @@ static NSString *cellId = @&quot;cellId&quot;;
287 587 // Dispose of any resources that can be recreated.
288 588 }
289 589  
290   -
291 590 @end
... ...
CNLiveChatSDKDemo/CNLiveChatSDKDemo/MessageModel.h
... ... @@ -10,7 +10,44 @@
10 10  
11 11 @interface MessageModel : NSObject
12 12  
13   -@property (nonatomic, strong) NSString *message;
  13 +@property (nonatomic, strong) NSString *message; // 文本消息
  14 +
  15 +/*!
  16 + 图片消息的URL地址
  17 +
  18 + @discussion 发送方此字段为图片的本地路径,接收方此字段为网络URL地址。
  19 + */
  20 +@property(nonatomic, strong) NSString *imageUrl;
  21 +
  22 +/*!
  23 + 图片消息的缩略图
  24 + */
  25 +@property(nonatomic, strong) UIImage *thumbnailImage;
  26 +/*!
  27 + 是否发送原图
  28 +
  29 + @discussion 在发送图片的时候,是否发送原图,默认值为NO。
  30 + */
  31 +@property(nonatomic, assign) BOOL isFull;
  32 +/*!
  33 + 图片消息的原始图片信息
  34 + */
  35 +@property(nonatomic, strong) UIImage *originalImage;
  36 +
  37 +/*!
  38 + wav格式的音频数据
  39 + */
  40 +@property(nonatomic, strong) NSData *wavAudioData;
  41 +
  42 +/*!
  43 + 语音消息的时长
  44 + */
  45 +@property(nonatomic, assign) long duration;
  46 +
  47 +/*!
  48 + 语音/图片消息的附加信息
  49 + */
  50 +@property(nonatomic, strong) NSString *extra;
14 51  
15 52 @property (nonatomic, strong) NSString *targetId;
16 53  
... ...
CNLiveChatSDKDemo/CNLiveChatSDKDemo/PrefixHeader.pch
... ... @@ -18,6 +18,11 @@
18 18 #import "MessageModel.h"
19 19 #import <CNLiveChatManager/CNLiveCommentManager.h>
20 20 #import "praiseModel.h"
  21 +#import <AVFoundation/AVFoundation.h>
  22 +#import <CNLiveChatManager/CNLiveChatVoiceMessage.h>
  23 +#import <CNLiveChatManager/CNliveChatImageMessage.h>
  24 +#import "CNLiveImageTableViewCell.h"
  25 +#import "CNLiveVoiceTableViewCell.h"
21 26  
22 27 #endif
23 28  
... ...
CNLiveChatSDKDemo/CNLiveChatSDKDemo/PrivateViewController.m
... ... @@ -8,18 +8,36 @@
8 8  
9 9 #import "PrivateViewController.h"
10 10  
11   -static NSString *priCellId = @"priCellId";
  11 +#define privateUserId @"67_170718"
  12 +
  13 +static NSString *textCellId = @"textCellId";
  14 +static NSString *voiceCellId = @"voiceCellId";
  15 +static NSString *imageCellId = @"imageCellId";
12 16  
13 17 @interface PrivateViewController ()<UITextFieldDelegate, CNLiveChatManagerDelegate, UITableViewDelegate, UITableViewDataSource> {
14 18  
15 19 NSMutableArray *_messageArrayM;
16   - NSString *_messageSelf;
  20 + BOOL _isVoice;
  21 + NSTimer *_getCountTimer;
17 22 }
18 23  
  24 +@property (nonatomic, strong) UIView *textViewBackView;
  25 +
19 26 @property (nonatomic, strong) UITextField *textField;
20 27  
21 28 @property (nonatomic, strong) UITableView *tableView;
22 29  
  30 +@property (nonatomic, strong) UIButton *imgButton;
  31 +
  32 +@property (nonatomic, strong) UIButton *voiceButton;
  33 +
  34 +@property (nonatomic, strong) UIButton *voiceSendBtn;
  35 +
  36 +@property (nonatomic, strong) AVAudioRecorder *recorder;// 录音
  37 +@property (nonatomic, strong) NSURL *recordTempFileURL; // 录音临时地址
  38 +@property (nonatomic, strong) NSData *recordedData; // 录音数据
  39 +@property (nonatomic, assign) NSTimeInterval duration; // 录音时长
  40 +
23 41 @end
24 42  
25 43 @implementation PrivateViewController
... ... @@ -27,153 +45,219 @@ static NSString *priCellId = @&quot;priCellId&quot;;
27 45 - (void)viewDidLoad {
28 46 [super viewDidLoad];
29 47  
30   - self.title = @"单聊";
31   -
32 48 self.view.backgroundColor = [UIColor whiteColor];
33   -
  49 + self.title = @"单聊";
  50 + [self addNotification];
34 51 self.automaticallyAdjustsScrollViewInsets = NO;
35 52  
36 53 [CNLiveChatManager sharedCNLiveChatManager].delegate = self;
37 54  
38 55 [self.view addSubview:self.tableView];
39 56 UITapGestureRecognizer *gestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(hideKeyboard)];
40   - gestureRecognizer.cancelsTouchesInView = NO;
  57 + gestureRecognizer.cancelsTouchesInView = YES;
41 58 [self.tableView addGestureRecognizer:gestureRecognizer];
42   - [self.view addSubview:self.textField];
  59 + [self.view addSubview:self.textViewBackView];
43 60  
44 61 _messageArrayM = [[NSMutableArray alloc] init];
45 62  
46 63 // 获取最新消息
47 64 [self getPrivateChattingRecords];
48   -
49   - // 获取昵称信息
50   - NSString *name = [CNLiveChatManager sharedCNLiveChatManager].currentUserInfo.name;
51   - NSLog(@"昵称:%@",name);
52 65 }
53 66  
54   -#pragma mark - 懒加载 !!!!!!!!!!!!!!!!!!!!!!!!!!
55   -- (UITextField *)textField {
  67 +#pragma mark - 获取私聊最新历史聊天记录 !!!!!!!!!!!!!!!!!!!!!!!!!!!!
  68 +- (void)getPrivateChattingRecords {
56 69  
57   - if (!_textField) {
58   - _textField = [self createTextFieldWithFrame:CGRectMake(10, 74, KScreenWidth - 20, 40) font:20];
59   - _textField.delegate = self;
60   - }
61   - return _textField;
62   -}
  70 + // 获取最新消息
  71 + NSArray *messageArray = [[CNLiveChatManager sharedCNLiveChatManager] getLatestMessages:CNLive_ConversationType_PRIVATE targetId:privateUserId count:20];
  72 +
  73 + for (id message in messageArray) {
  74 +
  75 + if ([message isKindOfClass:[CNLiveChatMessage class]]) {
  76 +
  77 + CNLiveChatMessage *textMsg = (CNLiveChatMessage *)message;
  78 + MessageModel *model = [[MessageModel alloc] init];
  79 + model.message = textMsg.messageContent;
  80 + model.userId = textMsg.userInfo.userId;
  81 + model.name = textMsg.userInfo.name;
  82 + model.portraitUri = textMsg.userInfo.portraitUri;
  83 + model.type = textMsg.conversationType;
  84 + if (![_messageArrayM containsObject:model]) {
  85 + [_messageArrayM insertObject:model atIndex:0];
  86 + }
  87 +
  88 + } else if ([message isKindOfClass:[CNliveChatImageMessage class]]) {
63 89  
64   --(UITableView *)tableView {
65   - if (!_tableView) {
66   - _tableView = [[UITableView alloc] initWithFrame:CGRectMake(0, 124, KScreenWidth, KScreenHeight - 425) style:UITableViewStylePlain];
67   - _tableView.rowHeight = 30;
68   - _tableView.delegate = self;
69   - _tableView.dataSource = self;
70   - [_tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:priCellId];
  90 + CNliveChatImageMessage *imageMsg = (CNliveChatImageMessage *)message;
  91 + MessageModel *model = [[MessageModel alloc] init];
  92 + model.imageUrl = imageMsg.imageUrl;
  93 + model.thumbnailImage = imageMsg.thumbnailImage;
  94 + model.isFull = imageMsg.isFull;
  95 + model.originalImage = imageMsg.originalImage;
  96 + model.extra = imageMsg.extra;
  97 + model.userId = imageMsg.userInfo.userId;
  98 + model.name = imageMsg.userInfo.name;
  99 + model.portraitUri = imageMsg.userInfo.portraitUri;
  100 + model.type = imageMsg.conversationType;
  101 + if (![_messageArrayM containsObject:model]) {
  102 + [_messageArrayM insertObject:model atIndex:0];
  103 + }
  104 +
  105 + } else if ([message isKindOfClass:[CNLiveChatVoiceMessage class]]) {
  106 +
  107 + CNLiveChatVoiceMessage *voiceMsg = (CNLiveChatVoiceMessage *)message;
  108 + MessageModel *model = [[MessageModel alloc] init];
  109 + model.wavAudioData = voiceMsg.wavAudioData;
  110 + model.duration = voiceMsg.duration;
  111 + model.extra = voiceMsg.extra; // 扩展
  112 + model.targetId = voiceMsg.targetId;
  113 + model.userId = voiceMsg.userInfo.userId;
  114 + model.name = voiceMsg.userInfo.name;
  115 + model.portraitUri = voiceMsg.userInfo.portraitUri;
  116 + model.type = voiceMsg.conversationType;
  117 + if (![_messageArrayM containsObject:model]) {
  118 + [_messageArrayM insertObject:model atIndex:0];
  119 + }
  120 + }
  121 + [self.tableView reloadData];
  122 + [self scrollToBottom];
71 123 }
72   - return _tableView;
73 124 }
74 125  
75 126 #pragma mark - UITableViewDelegate,UITableViewDataSource !!!!!!!!!!!!!!!!!!!!!!!!!!
76 127  
77   -- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
78   - return 1;
79   -}
80   -
81 128 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
82 129 return _messageArrayM.count;
83 130 }
84 131  
85   -- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
86   -
87   - UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:priCellId forIndexPath:indexPath];
  132 +- (id)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
88 133  
89 134 MessageModel *model = _messageArrayM[indexPath.row];
90 135  
91   - NSMutableAttributedString *AttributedStr = [[NSMutableAttributedString alloc]initWithString:[NSString stringWithFormat:@"%@: %@",model.name,model.message]];
92   -
93   - if ([model.userId isEqualToString:[CNLiveChatManager sharedCNLiveChatManager].currentUserInfo.userId]) {
  136 + if (model.message) { // 文本消息
  137 + UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:textCellId forIndexPath:indexPath];
  138 + NSMutableAttributedString *AttributedStr = [[NSMutableAttributedString alloc]initWithString:[NSString stringWithFormat:@"%@: %@",model.name,model.message]];
94 139  
95   - [AttributedStr addAttribute:NSForegroundColorAttributeName
96   -
97   - value:[UIColor redColor]
98   -
99   - range:NSMakeRange(0, model.name.length)];
  140 + if ([model.userId isEqualToString:[CNLiveChatManager sharedCNLiveChatManager].currentUserInfo.userId]) {
  141 + [AttributedStr addAttribute:NSForegroundColorAttributeName
  142 + value:[UIColor redColor]
  143 + range:NSMakeRange(0, model.name.length)];
  144 + cell.textLabel.attributedText = AttributedStr;
  145 + } else {
  146 + [AttributedStr addAttribute:NSForegroundColorAttributeName
  147 + value:[UIColor blackColor]
  148 + range:NSMakeRange(0, model.name.length)];
  149 + cell.textLabel.attributedText = AttributedStr;
  150 + }
  151 + return cell;
100 152  
101   - cell.textLabel.attributedText = AttributedStr;
102   - } else {
  153 + } else if (model.wavAudioData) { // 语音消息
103 154  
104   - [AttributedStr addAttribute:NSForegroundColorAttributeName
105   -
106   - value:[UIColor blackColor]
107   -
108   - range:NSMakeRange(0, model.name.length)];
  155 + CNLiveVoiceTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:voiceCellId forIndexPath:indexPath];
  156 + cell.model = model;
  157 + return cell;
  158 + } else if (model.wavAudioData || model.thumbnailImage) { // 图片消息
109 159  
110   - cell.textLabel.attributedText = AttributedStr;
  160 + CNLiveImageTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:imageCellId forIndexPath:indexPath];
  161 + cell.model = model;
  162 + return cell;
111 163 }
112   -
113   - return cell;
  164 + return nil;
114 165 }
115 166  
  167 +- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
  168 +
  169 + MessageModel *model = _messageArrayM[indexPath.row];
  170 + if (model.wavAudioData) {
  171 + return 50;
  172 + } else if (model.imageUrl || model.thumbnailImage) {
  173 + return 100;
  174 + }
  175 + return 30;
  176 +}
116 177  
117 178 #pragma mark - UITextFieldDelegate !!!!!!!!!!!!!!!!!!!!!!!!!!
118   -- (BOOL)textFieldShouldReturn:(UITextField *)textField { // 发送消息
  179 +- (BOOL)textFieldShouldReturn:(UITextField *)textField { // 发送文本消息
119 180  
120   - [[CNLiveChatManager sharedCNLiveChatManager] sendMessage:textField.text type:CNLive_ConversationType_PRIVATE targetId:@"70_20170315" success:^(CNLiveChatMessage *message) {
  181 + [[CNLiveChatManager sharedCNLiveChatManager] sendMessage:textField.text type:CNLive_ConversationType_PRIVATE targetId:privateUserId success:^(id message) {
121 182  
122   - NSLog(@"发送消息成功:%@",message.messageId);
123 183 // 自己发送的消息不会被onReceived:方法实时监听,需要自己做处理
124   - MessageModel *model = [[MessageModel alloc] init];
125   -
126   - model.message = _messageSelf;
127   - CNLiveChatUserInfo *userInfo = [CNLiveChatManager sharedCNLiveChatManager].currentUserInfo;
128   - model.userId = userInfo.userId;
129   - model.name = userInfo.name;
130   - model.portraitUri = userInfo.portraitUri;
131   - model.type = CNLive_ConversationType_CHATROOM;
132   - model.messageId = message.messageId;
133   -
134   - [_messageArrayM addObject:model];
135   -
136   - // 此处更新 UI 应到主线程
137   - dispatch_async(dispatch_get_main_queue(), ^{
  184 + if ([message isKindOfClass:[CNLiveChatMessage class]]) {
138 185  
139   - [self.tableView reloadData];
  186 + CNLiveChatMessage *textMsg = message;
  187 + NSLog(@"文本消息发送成功:%@",textMsg.messageContent);
  188 + MessageModel *model = [[MessageModel alloc] init];
  189 + model.message = textMsg.messageContent;
  190 + model.userId = textMsg.userInfo.userId;
  191 + model.name = textMsg.userInfo.name;
  192 + model.portraitUri = textMsg.userInfo.portraitUri;
  193 + model.type = textMsg.conversationType;
  194 + model.messageId = textMsg.messageId;
  195 + [_messageArrayM addObject:model];
140 196  
141   - [self scrollToBottom];
142   - });
  197 + // 此处更新 UI 应到主线程
  198 + dispatch_async(dispatch_get_main_queue(), ^{
  199 + [self.tableView reloadData];
  200 + [self scrollToBottom];
  201 + });
  202 + }
143 203  
144 204 } error:^(CNLiveChatErrorCode errors, NSString *messageId, NSString *targetId) {
145   -
146   - NSLog(@"向:%@发送消息失败,错误代码:%ld,信息ID:%@",targetId,(long)errors,messageId);
  205 + NSLog(@"发送文本消息失败,错误代码:%ld",(long)errors);
147 206 }];
148 207  
149   - _messageSelf = textField.text;
150 208 textField.text = @"";
151   -
152 209 return YES;
153 210 }
154 211  
155 212  
156 213 #pragma mark - CNLiveChatManagerDelegate !!!!!!!!!!!!!!!!!!!!!!!!!!
157   -- (void)onReceived:(CNLiveChatMessage *)message {
158   -
159   - NSLog(@"收到消息类型:%lu,消息ID:%@,消息内容:%@,消息发送者信息:%@",(unsigned long)message.conversationType,message.targetId,message.messageContent,message.userInfo);
  214 +- (void)onReceived:(id)message {
160 215  
161   - if (message.conversationType == CNLive_ConversationType_PRIVATE) {
  216 + if ([message isKindOfClass:[CNLiveChatMessage class]]) {
162 217  
  218 + CNLiveChatMessage * msg = (CNLiveChatMessage *)message;
  219 +
163 220 MessageModel *model = [[MessageModel alloc] init];
  221 + model.message = msg.messageContent;
  222 + model.userId = msg.userInfo.userId;
  223 + model.name = msg.userInfo.name;
  224 + model.portraitUri = msg.userInfo.portraitUri;
  225 + model.type = msg.conversationType;
  226 + [_messageArrayM addObject:model];
164 227  
165   - model.message = message.messageContent;
166   - model.userId = message.userInfo.userId;
167   - model.name = message.userInfo.name;
168   - model.portraitUri = message.userInfo.portraitUri;
169   - model.type = message.conversationType;
  228 + } else if ([message isKindOfClass:[CNliveChatImageMessage class]]) {
170 229  
  230 + CNliveChatImageMessage * msg = (CNliveChatImageMessage *)message;
  231 +
  232 + MessageModel *model = [[MessageModel alloc] init];
  233 + model.imageUrl = msg.imageUrl;
  234 + model.thumbnailImage = msg.thumbnailImage;
  235 + model.isFull = msg.isFull;
  236 + model.originalImage = msg.originalImage;
  237 + model.extra = msg.extra;
  238 + model.userId = msg.userInfo.userId;
  239 + model.name = msg.userInfo.name;
  240 + model.portraitUri = msg.userInfo.portraitUri;
  241 + model.type = msg.conversationType;
171 242 [_messageArrayM addObject:model];
172 243  
173   - [self.tableView reloadData];
  244 + } else if ([message isKindOfClass:[CNLiveChatVoiceMessage class]]) {
174 245  
175   - [self scrollToBottom];
  246 + CNLiveChatVoiceMessage * msg = (CNLiveChatVoiceMessage *)message;
  247 +
  248 + MessageModel *model = [[MessageModel alloc] init];
  249 + model.wavAudioData = msg.wavAudioData;
  250 + model.duration = msg.duration;
  251 + model.extra = msg.extra; // 扩展
  252 + model.targetId = msg.targetId;
  253 + model.userId = msg.userInfo.userId;
  254 + model.name = msg.userInfo.name;
  255 + model.portraitUri = msg.userInfo.portraitUri;
  256 + model.type = msg.conversationType;
  257 + [_messageArrayM addObject:model];
176 258 }
  259 + [self.tableView reloadData];
  260 + [self scrollToBottom];
177 261 }
178 262  
179 263 - (void)onConnectionStatusChanged:(CNLiveConnectionStatus)status {
... ... @@ -183,10 +267,211 @@ static NSString *priCellId = @&quot;priCellId&quot;;
183 267  
184 268 - (void)kickedByAnotherDevice {
185 269  
  270 + [_messageArrayM removeAllObjects];
186 271 NSString *userId = [CNLiveChatManager sharedCNLiveChatManager].currentUserInfo.userId;
187 272 NSLog(@"账号%@在其他设备登陆",userId);
188 273 }
189 274  
  275 +#pragma mark - 图片 Button Action !!!!!!!!!!!!!!!!!!!!!!!!
  276 +- (void)sendImage {
  277 +
  278 + NSString *path = [[NSBundle mainBundle] pathForResource:@"tu.jpg" ofType:nil];
  279 + CNliveChatImageMessage *imageMsg = [CNliveChatImageMessage messageWithImageURI:path];
  280 +
  281 + [[CNLiveChatManager sharedCNLiveChatManager] sendMediaMessage:CNLive_ConversationType_PRIVATE targetId:privateUserId content:imageMsg progress:^(int progress, NSString *messageId) {
  282 + NSLog(@"发送进度");
  283 + } success:^(CNliveChatImageMessage *message) {
  284 +
  285 + NSLog(@"图片消息发送成功~");
  286 + MessageModel *model = [[MessageModel alloc] init];
  287 + model.imageUrl = message.imageUrl;
  288 + model.thumbnailImage = message.thumbnailImage;
  289 + model.isFull = message.isFull;
  290 + model.originalImage = message.originalImage;
  291 + model.extra = message.extra;
  292 + model.userId = message.userInfo.userId;
  293 + model.name = message.userInfo.name;
  294 + model.portraitUri = message.userInfo.portraitUri;
  295 + model.type = message.conversationType;
  296 + model.messageId = message.messageId;
  297 + [_messageArrayM addObject:model];
  298 +
  299 + // 此处更新 UI 应到主线程
  300 + dispatch_async(dispatch_get_main_queue(), ^{
  301 + [self.tableView reloadData];
  302 + [self scrollToBottom];
  303 + });
  304 +
  305 + } error:^(CNLiveChatErrorCode errorCode, NSString *messageId) {
  306 + NSLog(@"发送图片消息失败,错误码:%ld",(long)errorCode);
  307 + }];
  308 +}
  309 +
  310 +#pragma mark - 语音 Button Action !!!!!!!!!!!!!!!!!!!!!!!!
  311 +- (void)voiceAction {
  312 +
  313 + _isVoice = !_isVoice;
  314 + if (_isVoice) {
  315 + [self.textField removeFromSuperview];
  316 + [self.textViewBackView addSubview:self.voiceSendBtn];
  317 + } else {
  318 + [self.voiceSendBtn removeFromSuperview];
  319 + [self.textViewBackView addSubview:self.textField];
  320 + }
  321 +}
  322 +
  323 +- (void)startRecord {
  324 + NSLog(@"讲话");
  325 +
  326 + [self.recorder prepareToRecord];
  327 +
  328 + [self.recorder record];
  329 +}
  330 +
  331 +- (void)stopRecord {
  332 + NSLog(@"松手");
  333 +
  334 + if (self.recorder.isRecording) {
  335 + self.recordedData =[NSData dataWithContentsOfURL:self.recordTempFileURL];
  336 + self.duration = self.recorder.currentTime;
  337 + [self.recorder stop];
  338 + self.recorder = nil;
  339 + }
  340 +
  341 + if (self.recordedData && self.duration > 1) {
  342 +
  343 + CNLiveChatVoiceMessage *voiceMsg = [CNLiveChatVoiceMessage messageWithAudio:self.recordedData duration:self.duration];
  344 +
  345 + [[CNLiveChatManager sharedCNLiveChatManager] sendMessage:voiceMsg type:CNLive_ConversationType_PRIVATE targetId:privateUserId success:^(id message) {
  346 +
  347 + NSLog(@"语音消息发送成功");
  348 + // 自己发送的消息不会被onReceived:方法实时监听,需要自己做处理
  349 + if ([message isKindOfClass:[CNLiveChatVoiceMessage class]]) {
  350 +
  351 + CNLiveChatVoiceMessage *voiceMsg = message;
  352 + MessageModel *model = [[MessageModel alloc] init];
  353 +
  354 + model.wavAudioData = voiceMsg.wavAudioData;
  355 + model.duration = voiceMsg.duration;
  356 + model.extra = voiceMsg.extra; // 扩展
  357 + model.targetId = voiceMsg.targetId;
  358 + CNLiveChatUserInfo *userInfo = [CNLiveChatManager sharedCNLiveChatManager].currentUserInfo;
  359 + model.userId = userInfo.userId;
  360 + model.name = userInfo.name;
  361 + model.portraitUri = userInfo.portraitUri;
  362 + model.type = CNLive_ConversationType_PRIVATE;
  363 +
  364 + [_messageArrayM addObject:model];
  365 +
  366 + // 此处更新 UI 应到主线程
  367 + dispatch_async(dispatch_get_main_queue(), ^{
  368 +
  369 + [self.tableView reloadData];
  370 +
  371 + [self scrollToBottom];
  372 + });
  373 + }
  374 +
  375 + } error:^(CNLiveChatErrorCode errors, NSString *messageId, NSString *targetId) {
  376 + NSLog(@"语音发送失败,错误码:%ld",errors);
  377 + }];
  378 + } else {
  379 + NSLog(@"时间太短,重新录制");
  380 + }
  381 +}
  382 +
  383 +#pragma mark - Get Method !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  384 +- (UIView *)textViewBackView {
  385 + if (!_textViewBackView) {
  386 + _textViewBackView = [[UIView alloc] initWithFrame:CGRectMake(0, KScreenHeight-50, KScreenWidth, 50)];
  387 + _textViewBackView.backgroundColor = [UIColor colorWithRed:(230.0/255.0) green:(230.0/255.0) blue:(230.0/255.0) alpha:1];
  388 + [_textViewBackView addSubview:self.textField];
  389 + [_textViewBackView addSubview:self.voiceButton];
  390 + [_textViewBackView addSubview:self.imgButton];
  391 + }
  392 + return _textViewBackView;
  393 +}
  394 +
  395 +- (UITextField *)textField {
  396 +
  397 + if (!_textField) {
  398 + _textField = [self createTextFieldWithFrame:CGRectMake(43, 5, KScreenWidth - 86, 40) font:20];
  399 + _textField.delegate = self;
  400 + }
  401 + return _textField;
  402 +}
  403 +
  404 +-(UITableView *)tableView {
  405 + if (!_tableView) {
  406 + _tableView = [[UITableView alloc] initWithFrame:CGRectMake(0, 64, KScreenWidth, KScreenHeight - 114) style:UITableViewStylePlain];
  407 + _tableView.rowHeight = 30;
  408 + _tableView.delegate = self;
  409 + _tableView.dataSource = self;
  410 + [_tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:textCellId];
  411 + [_tableView registerClass:[CNLiveVoiceTableViewCell class] forCellReuseIdentifier:voiceCellId];
  412 + [_tableView registerClass:[CNLiveImageTableViewCell class] forCellReuseIdentifier:imageCellId];
  413 + }
  414 + return _tableView;
  415 +}
  416 +
  417 +- (UIButton *)imgButton {
  418 + if (!_imgButton) {
  419 + _imgButton = [UIButton buttonWithType:UIButtonTypeCustom];
  420 + _imgButton.frame = CGRectMake(KScreenWidth - 40, 5, 40, 40);
  421 + [_imgButton setImage:[UIImage imageNamed:@"加号"] forState:UIControlStateNormal];
  422 + [_imgButton addTarget:self action:@selector(sendImage) forControlEvents:UIControlEventTouchUpInside];
  423 + }
  424 + return _imgButton;
  425 +}
  426 +
  427 +- (UIButton *)voiceButton {
  428 + if (!_voiceButton) {
  429 + _voiceButton = [UIButton buttonWithType:UIButtonTypeCustom];
  430 + _voiceButton.frame = CGRectMake(0, 5, 40, 40);
  431 + [_voiceButton setImage:[UIImage imageNamed:@"语音"] forState:UIControlStateNormal];
  432 + [_voiceButton addTarget:self action:@selector(voiceAction) forControlEvents:UIControlEventTouchUpInside];
  433 + }
  434 + return _voiceButton;
  435 +}
  436 +
  437 +- (UIButton *)voiceSendBtn {
  438 + if (!_voiceSendBtn) {
  439 + _voiceSendBtn = [UIButton buttonWithType:UIButtonTypeCustom];
  440 + _voiceSendBtn.frame = CGRectMake(43, 5, KScreenWidth - 86, 40);
  441 + [_voiceSendBtn setTitle:@"按住 说话" forState:UIControlStateNormal];
  442 + [_voiceSendBtn setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
  443 + [_voiceSendBtn setTitle:@"松手 发送" forState:UIControlStateHighlighted];
  444 + [_voiceSendBtn setTitleColor:[UIColor blackColor] forState:UIControlStateHighlighted];
  445 + _voiceSendBtn.backgroundColor = [UIColor whiteColor];
  446 + [_voiceSendBtn addTarget:self action:@selector(startRecord) forControlEvents:UIControlEventTouchDown];
  447 + [_voiceSendBtn addTarget:self action:@selector(stopRecord) forControlEvents:UIControlEventTouchUpInside];
  448 + }
  449 + return _voiceSendBtn;
  450 +}
  451 +
  452 +- (AVAudioRecorder *)recorder { // 录音
  453 + if (!_recorder) {
  454 + NSDictionary *settings = @{AVFormatIDKey: @(kAudioFormatLinearPCM),
  455 + AVSampleRateKey: @8000.00f,
  456 + AVNumberOfChannelsKey: @1,
  457 + AVLinearPCMBitDepthKey: @16,
  458 + AVLinearPCMIsNonInterleaved: @NO,
  459 + AVLinearPCMIsFloatKey: @NO,
  460 + AVLinearPCMIsBigEndianKey: @NO};
  461 + NSError *error;
  462 + [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryRecord error:nil];
  463 + _recorder = [[AVAudioRecorder alloc] initWithURL:self.recordTempFileURL settings:settings error:&error];
  464 + }
  465 + return _recorder;
  466 +}
  467 +
  468 +- (NSURL *)recordTempFileURL {
  469 + if (!_recordTempFileURL) {
  470 + _recordTempFileURL = [NSURL fileURLWithPath:[NSTemporaryDirectory() stringByAppendingPathComponent: @"tempAC.caf"]];
  471 + }
  472 + return _recordTempFileURL;
  473 +}
  474 +
190 475  
191 476 #pragma mark - 创建文本框 !!!!!!!!!!!!!!!!!!!!!!!!!!
192 477 - (UITextField *)createTextFieldWithFrame:(CGRect)frame font:(float)font {
... ... @@ -202,33 +487,6 @@ static NSString *priCellId = @&quot;priCellId&quot;;
202 487 return textField;
203 488 }
204 489  
205   -#pragma mark - 获取私聊最新历史聊天记录 !!!!!!!!!!!!!!!!!!!!!!!!
206   -- (void)getPrivateChattingRecords {
207   -
208   - // 获取最新消息
209   - NSArray *messageArray = [[CNLiveChatManager sharedCNLiveChatManager] getLatestMessages:CNLive_ConversationType_PRIVATE targetId:@"70_20170315" count:100];
210   -
211   - for (CNLiveChatMessage *message in messageArray) {
212   -
213   - MessageModel *model = [[MessageModel alloc] init];
214   -
215   - model.message = message.messageContent;
216   - model.userId = message.userInfo.userId;
217   - model.name = message.userInfo.name;
218   - model.portraitUri = message.userInfo.portraitUri;
219   - model.type = message.conversationType;
220   -
221   - if (![_messageArrayM containsObject:model]) {
222   -
223   - [_messageArrayM insertObject:model atIndex:0];
224   - }
225   -
226   - [self.tableView reloadData];
227   -
228   - [self scrollToBottom];
229   - }
230   -}
231   -
232 490 #pragma mark - tableView 滚到最后一行 !!!!!!!!!!!!!!!!!!!!!!!!!!
233 491 - (void)scrollToBottom {
234 492  
... ... @@ -239,6 +497,72 @@ static NSString *priCellId = @&quot;priCellId&quot;;
239 497 }
240 498 }
241 499  
  500 +- (void)addNotification {
  501 + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
  502 + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];
  503 +}
  504 +
  505 +#pragma mark <KeyboardNotificationAction> !!!!!!!!!!!!!!!!!!!!!!!!!!!
  506 +- (void)keyboardWillShow:(NSNotification *)notification {
  507 +
  508 + CGRect keyboardRect = [[notification.userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];
  509 + UIViewAnimationCurve curve = [[notification.userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey] integerValue];
  510 + double duration = [[notification.userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];
  511 +
  512 + UIEdgeInsets contentInsets = UIEdgeInsetsMake(0.0,0.0,keyboardRect.size.height,0.0);
  513 + _tableView.contentInset = contentInsets;
  514 + [self scrollToBottom];
  515 +
  516 + [UIView animateWithDuration:duration
  517 + delay:0.0f
  518 + options:[self animationOptionsForCurve:curve]
  519 + animations:^{
  520 +
  521 + CGRect inputViewFrame = self.textViewBackView.frame;
  522 + if (keyboardRect.origin.y == KScreenHeight) {
  523 + self.textViewBackView.frame = CGRectMake(inputViewFrame.origin.x,
  524 + self.view.frame.size.height-(inputViewFrame.size.height),
  525 + inputViewFrame.size.width,
  526 + inputViewFrame.size.height);
  527 + } else {
  528 +
  529 + self.textViewBackView.frame = CGRectMake(inputViewFrame.origin.x,
  530 + self.view.frame.size.height-keyboardRect.size.height-_textViewBackView.frame.size.height,
  531 + inputViewFrame.size.width,
  532 + inputViewFrame.size.height);
  533 +
  534 + }
  535 + }
  536 + completion:^(BOOL finished) {
  537 + }];
  538 +}
  539 +
  540 +- (void)keyboardWillHide:(NSNotification *)notification
  541 +{
  542 + [self.textViewBackView setFrame:CGRectMake(0, KScreenHeight-50, KScreenWidth, self.textViewBackView.frame.size.height)];
  543 + _tableView.contentInset = UIEdgeInsetsZero;
  544 +}
  545 +
  546 +- (UIViewAnimationOptions)animationOptionsForCurve:(UIViewAnimationCurve)curve
  547 +{
  548 + switch (curve) {
  549 + case UIViewAnimationCurveEaseInOut:
  550 + return UIViewAnimationOptionCurveEaseInOut;
  551 + break;
  552 + case UIViewAnimationCurveEaseIn:
  553 + return UIViewAnimationOptionCurveEaseIn;
  554 + break;
  555 + case UIViewAnimationCurveEaseOut:
  556 + return UIViewAnimationOptionCurveEaseOut;
  557 + break;
  558 + case UIViewAnimationCurveLinear:
  559 + return UIViewAnimationOptionCurveLinear;
  560 + break;
  561 + }
  562 +
  563 + return kNilOptions;
  564 +}
  565 +
242 566 #pragma mark - 隐藏键盘 !!!!!!!!!!!!!!!!!!!!!!!
243 567 - (void)hideKeyboard {
244 568  
... ... @@ -250,6 +574,4 @@ static NSString *priCellId = @&quot;priCellId&quot;;
250 574 // Dispose of any resources that can be recreated.
251 575 }
252 576  
253   -
254   -
255 577 @end
... ...
CNLiveChatSDKDemo/CNLiveChatSDKDemo/tu.jpg 0 → 100644

38.5 KB