实现收发消息
- iOS
更新时间不可用
了解如何快速接入实时消息 RTM,完成环境准备、参数配置、示例运行和核心流程验证。
本文将指导你如何利用 RTM Objective-C SDK 构建简单的应用程序,内容涵盖了集成和开发的基础知识:开通声网账号、获取 SDK、发送消息、接收消息等。
准备工作
开始构建项目前,你需要完成开通 RTM 服务,并检查你的开发环境是否满足平台支持中的最低版本要求。
构建项目
1. 项目配置
根据以下步骤配置你的项目:
- 在 Xcode 中创建一个 iOS 平台下的 Single View App,项目设置如下:
- Product Name 设为
RtmQuickstart。 - Organization Identifier 设为
agora。 - User Interface 选择 Storyboard。
- Language 选择 Objective-C。
- Product Name 设为
- 通过以下任意一种方式获取最新的 RTM Objective-C SDK 并导入你的项目。
- 点击此处下载最新版本的 Objective-C SDK。
- 复制 SDK 包中
/libs路径下所有的xcframework文件至项目路径下。 - 打开 Xcode,进入 TARGETS > Project Name > General > Frameworks, Libraries, and Embedded Content 菜单。
- 点击 + > Add Other… > Add Files 添加所有的
xcframework文件,并确保添加的动态库 Embed 属性设置为 Embed & Sign。
添加完成后,项目会自动链接所需系统库。
-
开始前请确保你已安装 Cocoapods,如尚未安装 Cocoapods,参考 Getting Started with CocoaPods 安装说明。
-
在终端里进入项目根目录,并运行
pod init命令。项目文件夹下会生成一个Podfile文本文件。 -
打开
Podfile文件,修改文件为如下内容。注意将Your App替换为你的 Target 名称。Ruby platform :ios, '11.0' target 'Your App' do # 对于 2.2.8 及之后版本: pod 'ShengWang-Rtm', '2.3.0', :subspecs => ['RtmKit'] # 对于 2.2.7 版本: # pod 'ShengwangRtm', 'x.y.z' # 对于 2.2.6 及之前版本: # pod 'AgoraRtm', 'x.y.z' # 如需获取 2.2.0 之前的版本,请将包名修改为 AgoraRtm_iOS end -
在终端内运行
pod install命令安装声网 SDK。成功安装后,Terminal 中会显示Pod installation complete!。 -
成功安装后,项目文件夹下会生成一个后缀为
.xcworkspace的文件,通过 Xcode 打开该文件进行后续操作。
使用如下链接,通过 SPM (Swift Package Manager) 集成 SDK:
https://github.com/AgoraIO/AgoraRtm_Apple.git信息
如果你同时集成了 2.2.0 及以上版本的 RTM SDK 和 4.3.0 及以上版本的 RTC SDK,请参考 FAQ 处理集成问题。
2. 初始化 RTM
调用 RTM SDK 的任何 API 之前,需要先初始化一个 AgoraRtmClientKit 对象实例。参考如下步骤创建用户界面、初始化一个 AgoraRtmClientKit 对象实例。
-
创建用户界面。实时消息 App 一般会有如下输入框和按钮:
- 用户名、频道名、消息输入框
- 登录、登出按钮
- 订阅、取消订阅频道按钮
- 发送消息按钮
本节提供简易的 UI 界面设计以便于验证功能特性,你可以根据实际项目需求进行修改。
-
使用 Code View 打开
Main.storyboard并将文件内容替换为以下代码:XML <?xml version="1.0" encoding="UTF-8"?> <document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="21701" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="BYZ-38-t0r"> <device id="retina6_1" orientation="portrait" appearance="light"/> <dependencies> <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="21679"/> <capability name="Safe area layout guides" minToolsVersion="9.0"/> <capability name="System colors in document resources" minToolsVersion="11.0"/> <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/> </dependencies> <scenes> <!--View Controller--> <scene sceneID="tne-QT-ifu"> <objects> <viewController id="BYZ-38-t0r" customClass="ViewController" sceneMemberID="viewController"> <view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC"> <rect key="frame" x="0.0" y="0.0" width="414" height="896"/> <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> <subviews> <button opaque="NO" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="M2K-rz-dlO"> <rect key="frame" x="254" y="103" width="38" height="30"/> <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/> <state key="normal" title="Login"/> <connections> <action selector="Login:" destination="BYZ-38-t0r" eventType="touchUpInside" id="UEU-up-ksL"/> </connections> </button> <button opaque="NO" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="CZ1-G5-AkG"> <rect key="frame" x="326" y="103" width="48" height="30"/> <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/> <state key="normal" title="Logout"/> <connections> <action selector="Logout:" destination="BYZ-38-t0r" eventType="touchUpInside" id="a0d-8h-eyX"/> </connections> </button> <button opaque="NO" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="0px-1e-aMC"> <rect key="frame" x="242" y="172" width="62" height="30"/> <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/> <state key="normal" title="Subscribe"/> <connections> <action selector="SubscribeChannel:" destination="BYZ-38-t0r" eventType="touchUpInside" id="12c-US-VQk"/> </connections> </button> <button opaque="NO" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="SDQ-Zt-rBD"> <rect key="frame" x="307" y="172" width="87" height="30"/> <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/> <state key="normal" title="Unsubscribe"/> <connections> <action selector="UnsubscribeChannel:" destination="BYZ-38-t0r" eventType="touchUpInside" id="u4T-ze-wtj"/> </connections> </button> <textField opaque="NO" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="left" contentVerticalAlignment="center" text="User ID" borderStyle="roundedRect" textAlignment="natural" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="69v-UU-ObH"> <rect key="frame" x="40" y="99" width="187" height="34"/> <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/> <fontDescription key="fontDescription" type="system" pointSize="14"/> <textInputTraits key="textInputTraits"/> </textField> <textField opaque="NO" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="left" contentVerticalAlignment="center" text="Channel name" borderStyle="roundedRect" textAlignment="natural" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="dGk-g2-qHK"> <rect key="frame" x="40" y="168" width="187" height="34"/> <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/> <fontDescription key="fontDescription" type="system" pointSize="14"/> <textInputTraits key="textInputTraits"/> </textField> <button opaque="NO" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Qqk-6X-Tcb"> <rect key="frame" x="304" y="247" width="88" height="30"/> <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/> <state key="normal" title="Publish MSG"/> <connections> <action selector="SendMessageToMessageChannel:" destination="BYZ-38-t0r" eventType="touchUpInside" id="XcX-nz-fPl"/> </connections> </button> <textField opaque="NO" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="left" contentVerticalAlignment="center" text="Message content" borderStyle="roundedRect" textAlignment="natural" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="lKg-ap-M6p"> <rect key="frame" x="40" y="245" width="252" height="34"/> <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/> <fontDescription key="fontDescription" type="system" pointSize="14"/> <textInputTraits key="textInputTraits"/> </textField> <textView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" fixedFrame="YES" textAlignment="natural" translatesAutoresizingMaskIntoConstraints="NO" id="e1v-i8-spC"> <rect key="frame" x="40" y="416" width="330" height="428"/> <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/> <color key="backgroundColor" systemColor="systemBackgroundColor"/> <color key="textColor" systemColor="labelColor"/> <fontDescription key="fontDescription" type="system" pointSize="14"/> <textInputTraits key="textInputTraits" autocapitalizationType="sentences"/> </textView> </subviews> <viewLayoutGuide key="safeArea" id="6Tk-OE-BBY"/> <color key="backgroundColor" systemColor="systemBackgroundColor"/> </view> <connections> <outlet property="ChannelIDTextField" destination="dGk-g2-qHK" id="Iuh-ow-1MH"/> <outlet property="GroupMsgButton" destination="Qqk-6X-Tcb" id="TV4-sg-bY7"/> <outlet property="GroupMsgTextField" destination="lKg-ap-M6p" id="2Me-Z0-QIH"/> <outlet property="LoginButton" destination="M2K-rz-dlO" id="ZxJ-oV-UKy"/> <outlet property="LogoutButton" destination="CZ1-G5-AkG" id="ZQE-B7-yya"/> <outlet property="MsgTextView" destination="e1v-i8-spC" id="76J-8Q-kKp"/> <outlet property="SubsctibeButton" destination="0px-1e-aMC" id="9TL-8M-l6w"/> <outlet property="UnSubscribeButton" destination="SDQ-Zt-rBD" id="tgd-fK-EfO"/> <outlet property="UserIDTextField" destination="69v-UU-ObH" id="3BH-ci-t7A"/> </connections> </viewController> <placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/> </objects> <point key="canvasLocation" x="131.8840579710145" y="97.767857142857139"/> </scene> </scenes> <resources> <systemColor name="labelColor"> <color red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> </systemColor> <systemColor name="systemBackgroundColor"> <color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/> </systemColor> </resources> </document> -
打开
ViewController.h文件,将文件内容替换为如下代码:Objective-C #import <UIKit/UIKit.h> #import <AgoraRtmKit/AgoraRtmKit.h> @interface ViewController : UIViewController // Buttons @property (weak, nonatomic) IBOutlet UIButton *LoginButton; @property (weak, nonatomic) IBOutlet UIButton *LogoutButton; @property (weak, nonatomic) IBOutlet UIButton *SubsctibeButton; @property (weak, nonatomic) IBOutlet UIButton *UnSubscribeButton; @property (weak, nonatomic) IBOutlet UIButton *GroupMsgButton; // Textfields @property (weak, nonatomic) IBOutlet UITextField *UserIDTextField; @property (weak, nonatomic) IBOutlet UITextField *ChannelIDTextField; @property (weak, nonatomic) IBOutlet UITextField *GroupMsgTextField; @property (weak, nonatomic) IBOutlet UITextView *MsgTextView; @end
-
打开
ViewController.m文件,将文件内容替换为如下代码。你会发现此程序并不完整,不用紧张,我们在后续步骤中将一步步指导你补充完善代码。信息
你需要将示例中的
your_appid和your_token字段替换成你项目的 App ID 和 Token。在测试阶段,为快速验证功能,我们建议你在创建声网项目时将鉴权模式设置为调试模式,然后将示例中的your_appid和your_token字段都替换成你项目的 App ID。Objective-C #import "ViewController.h" @interface ViewController ()<AgoraRtmClientDelegate> @property(nonatomic, strong)AgoraRtmClientKit* kit; @property NSString* appID; @property NSString* token; @property NSString* uid; @property NSString* peerID; @property NSString* channelID; @property NSString* peerMsg; @property NSString* channelMsg; @property NSString* text; @property NSMutableArray* textArray; - (void)AddMsgToRecord:(NSString*)text; @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; // Enter your App ID self.appID = @"your_appid"; self.MsgTextView.textColor = UIColor.blueColor; self.textArray = [[NSMutableArray alloc]init]; } // Add the event listener // Add message to the UI TextView - (void)AddMsgToRecord:(NSString*)text { [self.textArray addObject:(self.text)]; self.MsgTextView.text = [self.textArray componentsJoinedByString:(@"\n")]; } - (IBAction)Login:(id)sender { self.uid = self.UserIDTextField.text; // Enter your token self.token = @"your_token"; AgoraRtmClientConfig* rtm_config = [[AgoraRtmClientConfig alloc] initWithAppId:_appID userId:_uid]; NSError* initError = nil; _kit = [[AgoraRtmClientKit alloc] initWithConfig:rtm_config delegate:self error:&initError]; if (initError != nil) { self.text = [NSString stringWithFormat:@"init error %@",initError]; NSLog(@"%@", self.text); [self AddMsgToRecord:(self.text)]; } // Log in the RTM server } - (IBAction)Logout:(id)sender { if (_kit != nil) { // Log out from the RTM server } } - (IBAction)SubscribeChannel:(id)sender { self.channelID = self.ChannelIDTextField.text; if (_kit != nil) { // Subscribe to a channel } } - (IBAction)UnsubscribeChannel:(id)sender { if (_kit == nil) return; // Unsubscribe from a channel } - (IBAction)SendMessageToMessageChannel:(id)sender { self.channelID = self.ChannelIDTextField.text; self.channelMsg = self.GroupMsgTextField.text; // Publish a message } @end
如需了解更多初始化的信息,查看初始配置。
3. 添加事件监听
事件监听程序帮助你实现频道中消息、事件到达后的处理逻辑,添加以下代码到你的程序中以显示收到的消息或事件通知:
// Paste the following code snippet below "Add the event listener" comment
- (void)rtmKit:(AgoraRtmClientKit *)rtmKit didReceiveMessageEvent:(AgoraRtmMessageEvent *)event {
NSLog(@"%@", self.text);
self.text = [NSString stringWithFormat:@"receive message\nFrom channel: %@\npublisher:%@\nmessage:%@\n",event.channelName,event.publisher, event.message.stringData];
[self AddMsgToRecord:(self.text)];
}4. 登录服务
你需要执行登录操作才能建立与 RTM 服务器的连接,然后才能调用 SDK 的其他 API。将以下代码添加到程序中:
// Paste the following code snippet below "Log in the RTM server" comment
[_kit loginByToken:self.token completion:^(AgoraRtmCommonResponse * _Nullable response, AgoraRtmErrorInfo * _Nullable errorInfo) {
if (errorInfo.errorCode != AgoraRtmErrorOk){
self.text = [NSString stringWithFormat:@"Login failed for user %@. Code: %ld",self.uid, (long)errorInfo.errorCode];
NSLog(@"%@", self.text);
} else {
NSLog(@"%@", self.text);
self.text = [NSString stringWithFormat:@"Login successful for user %@. Code: %ld",self.uid, (long)errorInfo.errorCode];
}
[self AddMsgToRecord:(self.text)];
}];5. 收发消息
调用 publish 方法向 Message Channel 发送消息后,RTM 会把该消息分发给该频道的所有订阅者,以下代码演示如何发送字符串类型的消息,将此代码片段添加到程序中:
信息
你需要先对消息负载进行字符串序列化,才能调用 publish 方法发送消息。
// Paste the following code snippet below "Publish a message" comment
[_kit publish:self.channelID message:self.channelMsg option:nil completion:^(AgoraRtmCommonResponse * _Nullable response, AgoraRtmErrorInfo * _Nullable errorInfo) {
if (errorInfo == nil) {
self.text = [NSString stringWithFormat:@"Message sent to channel %@ : %@", self.channelID, self.channelMsg];
} else {
self.text = [NSString stringWithFormat:@"Message failed to send to channel %@ : %@ ErrorCode: %ld", self.channelID, self.channelMsg, (long)errorInfo.errorCode];
}
[self AddMsgToRecord:(self.text)];
}];调用 subscribeWithChannel 方法订阅此频道以接收此频道中的消息。将以下代码添加到程序中:
// Paste the following code snippet below "Subscribe to a channel" comment
[_kit subscribeWithChannel:self.channelID option:nil completion:^(AgoraRtmCommonResponse * _Nullable response, AgoraRtmErrorInfo * _Nullable errorInfo) {
if(errorInfo == nil) {
self.text = [NSString stringWithFormat:@"Successfully subscribe channel %@",self.channelID];
NSLog(@"%@", self.text);
} else {
self.text = [NSString stringWithFormat:@"Failed to subscribe channel %@ Code: %ld",self.channelID, (long)errorInfo.errorCode];
NSLog(@"%@", self.text);
}
[self AddMsgToRecord:(self.text)];
}];如果你不再需要在此频道收发消息,你可以调用 unsubscribeWithChannel 方法取消订阅此频道。将以下代码添加到程序中:
// Paste the following code snippet below "Unsubscribe from a channel" comment
[_kit unsubscribeWithChannel:self.channelID completion:^(AgoraRtmCommonResponse * _Nullable response, AgoraRtmErrorInfo * _Nullable errorInfo) {
if (errorInfo == nil){
self.text = [NSString stringWithFormat:@"Leave channel successful"];
} else {
self.text = [NSString stringWithFormat:@"Failed to leave channel Code: %ld", (long)errorInfo.errorCode];
}
[self AddMsgToRecord:(self.text)];
}];如需了解更多收发消息的信息,查看消息。
6. 登出服务
当不再需要使用 RTM 服务时,你可以调用 logout 方法登出 RTM 系统。将以下代码添加到程序中:
// Paste the following code snippet below "Log out from the RTM server" comment
[_kit logout:^(AgoraRtmCommonResponse * _Nullable response, AgoraRtmErrorInfo * _Nullable errorInfo) {
if (errorInfo == nil){
self.text = [NSString stringWithFormat:@"Logout successful"];
NSLog(@"%@", self.text);
[_kit destroy];
_kit = nil;
} else {
self.text = [NSString stringWithFormat:@"Logout failed. Code: %ld",(long)errorInfo.errorCode];
NSLog(@"%@", self.text);
}
[self AddMsgToRecord:(self.text)];
}];信息
本操作会影响你账单中的 PCU 计费项。
7. 组合到一起
经过上述步骤,你程序中的代码应该如下所示:
#import "ViewController.h"
@interface ViewController ()<AgoraRtmClientDelegate>
@property(nonatomic, strong)AgoraRtmClientKit* kit;
@property NSString* appID;
@property NSString* token;
@property NSString* uid;
@property NSString* peerID;
@property NSString* channelID;
@property NSString* peerMsg;
@property NSString* channelMsg;
@property NSString* text;
@property NSMutableArray* textArray;
- (void)AddMsgToRecord:(NSString*)text;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Enter your App ID
self.appID = @"your_appid";
self.MsgTextView.textColor = UIColor.blueColor;
self.textArray = [[NSMutableArray alloc]init];
}
- (void)rtmKit:(AgoraRtmClientKit *)rtmKit didReceiveMessageEvent:(AgoraRtmMessageEvent *)event {
NSLog(@"%@", self.text);
self.text = [NSString stringWithFormat:@"receive message\nFrom channel: %@\npublisher:%@\nmessage:%@\n",event.channelName,event.publisher, event.message.stringData];
[self AddMsgToRecord:(self.text)];
}
// Add message to the UI TextView
- (void)AddMsgToRecord:(NSString*)text {
[self.textArray addObject:(self.text)];
self.MsgTextView.text = [self.textArray componentsJoinedByString:(@"\n")];
}
- (IBAction)Login:(id)sender {
self.uid = self.UserIDTextField.text;
// Enter your token
self.token = @"your_token";
AgoraRtmClientConfig* rtm_config = [[AgoraRtmClientConfig alloc] initWithAppId:_appID userId:_uid];
NSError* initError = nil;
_kit = [[AgoraRtmClientKit alloc] initWithConfig:rtm_config delegate:self error:&initError];
if (initError != nil) {
self.text = [NSString stringWithFormat:@"init error %@",initError];
NSLog(@"%@", self.text);
[self AddMsgToRecord:(self.text)];
}
// Log in the RTM server
[_kit loginByToken:self.token completion:^(AgoraRtmCommonResponse * _Nullable response, AgoraRtmErrorInfo * _Nullable errorInfo) {
if (errorInfo.errorCode != AgoraRtmErrorOk){
self.text = [NSString stringWithFormat:@"Login failed for user %@. Code: %ld",self.uid, (long)errorInfo.errorCode];
NSLog(@"%@", self.text);
} else {
NSLog(@"%@", self.text);
self.text = [NSString stringWithFormat:@"Login successful for user %@. Code: %ld",self.uid, (long)errorInfo.errorCode];
}
[self AddMsgToRecord:(self.text)];
}];
}
- (IBAction)Logout:(id)sender {
if (_kit != nil) {
// Log out from the RTM server
[_kit logout:^(AgoraRtmCommonResponse * _Nullable response, AgoraRtmErrorInfo * _Nullable errorInfo) {
if (errorInfo == nil){
self.text = [NSString stringWithFormat:@"Logout successful"];
NSLog(@"%@", self.text);
[_kit destroy];
_kit = nil;
} else {
self.text = [NSString stringWithFormat:@"Logout failed. Code: %ld",(long)errorInfo.errorCode];
NSLog(@"%@", self.text);
}
[self AddMsgToRecord:(self.text)];
}];
}
- (IBAction)SubscribeChannel:(id)sender {
self.channelID = self.ChannelIDTextField.text;
if (_kit != nil) {
// Subscribe to a channel
[_kit subscribeWithChannel:self.channelID option:nil completion:^(AgoraRtmCommonResponse * _Nullable response, AgoraRtmErrorInfo * _Nullable errorInfo) {
if(errorInfo == nil) {
self.text = [NSString stringWithFormat:@"Successfully subscribe channel %@",self.channelID];
NSLog(@"%@", self.text);
} else {
self.text = [NSString stringWithFormat:@"Failed to subscribe channel %@ Code: %ld",self.channelID, (long)errorInfo.errorCode];
NSLog(@"%@", self.text);
}
[self AddMsgToRecord:(self.text)];
}];
}
}
- (IBAction)UnsubscribeChannel:(id)sender {
if (_kit == nil)
return;
// Unsubscribe from a channel
[_kit unsubscribeWithChannel:self.channelID completion:^(AgoraRtmCommonResponse * _Nullable response, AgoraRtmErrorInfo * _Nullable errorInfo) {
if (errorInfo == nil){
self.text = [NSString stringWithFormat:@"Leave channel successful"];
} else {
self.text = [NSString stringWithFormat:@"Failed to leave channel Code: %ld", (long)errorInfo.errorCode]; }
[self AddMsgToRecord:(self.text)];
}];
}
- (IBAction)SendMessageToMessageChannel:(id)sender {
self.channelID = self.ChannelIDTextField.text;
self.channelMsg = self.GroupMsgTextField.text;
// Publish a message
[_kit publish:self.channelID message:self.channelMsg option:nil completion:^(AgoraRtmCommonResponse * _Nullable response, AgoraRtmErrorInfo * _Nullable errorInfo) {
if (errorInfo == nil)
{
self.text = [NSString stringWithFormat:@"Message sent to channel %@ : %@", self.channelID, self.channelMsg]; }
else
{
self.text = [NSString stringWithFormat:@"Message failed to send to channel %@ : %@ ErrorCode: %ld", self.channelID, self.channelMsg, (long)errorInfo.errorCode]; }
[self AddMsgToRecord:(self.text)];
}];
}
@end现在,你可以开始运行你的程序:
- 保存项目。
- 复制当前项目,使用相同的
appId和不同的userId。 - 运行上面的两个项目。成功运行后,你可以在两个设备中看到 App 界面。
- 将一个设备作为接收端,进行如下操作:
- 输入用户名,点击 Login。
- 输入频道名,点击 Subscribe。
- 将另一个设备作为发送端,进行如下操作:
- 输入不同的用户名,点击 Subscribe。
- 输入相同的频道名。
- 输入消息,点击 Publish MSG。
- 将上面的发送端和设备端互换,重复步骤 4 和 5。
如果两个设备均可收发消息,那么你已经成功集成并正确使用了 RTM 服务。
贯穿始终
相比于介绍如何写出代码,声网更愿意帮助你掌握上述程序编写的过程和逻辑。上述程序依次完成了以下操作,让你可以正确地收发消息:
- 设置并初始化 RTM 对象。
- 添加
didReceiveMessageEvent事件监听函数。 - 调用
loginByToken登录了 RTM 服务。 - 调用
subscribeWithChannel订阅了一个 Message Channel。 - 调用
publish发送消息。 - 调用
unsubscribeWithChannel取消订阅一个 Message Channel。 - 调用
logout登出 RTM 系统。
下一步
现在,你已经学会了如何使用 RTM Objective-C SDK 来实现 Message Channel 的收发消息功能。下一步,你可以通过 SDK 的 API 参考了解更多功能的使用方法。