登录 RTM 系统包括以下流程:
发送和接收点对点消息包括以下流程:
发送和接收频道消息包括以下流程:
参考以下步骤创建一个 Agora 项目:
Agora 会给每个项目自动分配一个 App ID 作为项目唯一标识。
在 Agora 控制台的项目管理页面,找到你的项目,点击 App ID 右侧的 图标,即可获取项目的 App ID。
参考以下步骤获取 App 证书:
在 Agora 控制台的项目管理页面,找到你的项目,点击配置。
点击主要证书下面的复制图标,即可获取项目的 App 证书。
为提高项目的安全性,Agora 推荐使用 Token 对即将登录 RTM 系统的用户进行鉴权。
为了方便测试,Agora 服务器提供部署签发 RTM Token 的功能。参考以下步骤获取 RTM Token:
login
时,请确保填入的用户 ID 与生成 RTM Token 时填入的用户 ID 一致。参考以下步骤在 Xcode 中创建一个 macOS 平台下的 App,项目设置如下:
RtmQuickstart
。agora
。在 Terminal 里进入项目根目录,并运行 pod init
命令。项目文件夹下会生成一个 Podfile 文本文件。
打开 Podfile 文件,修改文件为如下内容。
# platform :macos, '10.10'
target 'RtmQuickstart' do
use_frameworks!
pod 'AgoraRtm_macOS'
end
运行 pod update
命令更新本地库版本。
运行 pod install
命令安装 Agora SDK。成功安装后,Terminal 中会显示 Pod installation complete!
,此时项目文件夹下会生成一个 workspace 文件。
Main.storyboard
并将文件内容替换为以下代码:<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.Storyboard.XIB" version="3.0" toolsVersion="16097.2" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" initialViewController="XfG-lQ-9wD">
<dependencies>
<deployment identifier="macosx"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="16097.2"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
<!--Application-->
<scene sceneID="JPo-4y-FX3">
<objects>
<application id="hnw-xV-0zn" sceneMemberID="viewController">
<menu key="mainMenu" title="Main Menu" systemMenu="main" id="AYu-sK-qS6">
<items>
<menuItem title="RtmQuickstart" id="1Xt-HY-uBw">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="RtmQuickstart" systemMenu="apple" id="uQy-DD-JDr">
<items>
<menuItem title="About RtmQuickstart" id="5kV-Vb-QxS">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="orderFrontStandardAboutPanel:" target="Ady-hI-5gd" id="Exp-CZ-Vem"/>
</connections>
</menuItem>
<menuItem title="Quit RtmQuickstart" keyEquivalent="q" id="4sb-4s-VLi">
<connections>
<action selector="terminate:" target="Ady-hI-5gd" id="Te7-pn-YzF"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
</items>
</menu>
<connections>
<outlet property="delegate" destination="Voe-Tx-rLC" id="PrD-fu-P6m"/>
</connections>
</application>
<customObject id="Voe-Tx-rLC" customClass="AppDelegate"/>
<customObject id="YLy-65-1bz" customClass="NSFontManager"/>
<customObject id="Ady-hI-5gd" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="75" y="0.0"/>
</scene>
<!--Window Controller-->
<scene sceneID="R2V-B0-nI4">
<objects>
<windowController id="B8D-0N-5wS" sceneMemberID="viewController">
<window key="window" title="Window" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" releasedWhenClosed="NO" visibleAtLaunch="NO" animationBehavior="default" id="IQv-IB-iLA">
<windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES" resizable="YES"/>
<windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
<rect key="contentRect" x="196" y="240" width="633" height="270"/>
<rect key="screenRect" x="0.0" y="0.0" width="1680" height="1027"/>
<connections>
<binding destination="B8D-0N-5wS" name="representedFilename" keyPath="self.MsgTextView" id="IH6-q2-gSp"/>
<outlet property="delegate" destination="B8D-0N-5wS" id="98r-iN-zZc"/>
</connections>
</window>
<connections>
<segue destination="XfG-lQ-9wD" kind="relationship" relationship="window.shadowedContentViewController" id="cq2-FE-JQM"/>
</connections>
</windowController>
<customObject id="Oky-zY-oP4" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="151.5" y="250"/>
</scene>
<!--View Controller-->
<scene sceneID="hIz-AP-VOD">
<objects>
<viewController id="XfG-lQ-9wD" customClass="ViewController" sceneMemberID="viewController">
<view key="view" id="m2S-Jp-Qdl">
<rect key="frame" x="0.0" y="0.0" width="672" height="466"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<textField verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Vhs-Qx-cHl">
<rect key="frame" x="117" y="393" width="172" height="27"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" borderStyle="bezel" drawsBackground="YES" id="4qa-bq-d5v">
<font key="font" usesAppearanceFont="YES"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="6pf-RU-bA5">
<rect key="frame" x="36" y="399" width="49" height="16"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" lineBreakMode="clipping" title="User ID" id="l8T-HD-eJJ">
<font key="font" metaFont="system"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="7dp-23-vRo">
<rect key="frame" x="36" y="348" width="67" height="16"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" lineBreakMode="clipping" title="ChannelID" id="LCQ-eF-Nf6">
<font key="font" metaFont="system"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<textField verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="7zu-6p-vJj">
<rect key="frame" x="117" y="342" width="172" height="27"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" borderStyle="bezel" drawsBackground="YES" id="4NN-2G-iTL">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<textField verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="eZF-Je-F07">
<rect key="frame" x="117" y="284" width="360" height="27"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" borderStyle="bezel" drawsBackground="YES" id="x8V-FH-HnS">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Ubg-em-Lwh">
<rect key="frame" x="10" y="293" width="100" height="16"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" lineBreakMode="clipping" title="Group Message" id="iKx-sY-uuc">
<font key="font" metaFont="system"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="hnI-nz-lHy">
<rect key="frame" x="12" y="247" width="90" height="16"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" lineBreakMode="clipping" title="Peer Message" id="HNY-nO-pn1">
<font key="font" metaFont="system"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<textField verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="l5d-LC-xJP">
<rect key="frame" x="117" y="237" width="360" height="28"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" borderStyle="bezel" drawsBackground="YES" id="Itb-hN-7on">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="8ld-U7-qEb">
<rect key="frame" x="381" y="389" width="74" height="32"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<buttonCell key="cell" type="push" title="Login" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="ZIB-oj-s8Y">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<action selector="Login:" target="XfG-lQ-9wD" id="Pfy-Nu-Lmf"/>
</connections>
</button>
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="h2Z-Uu-Bpv">
<rect key="frame" x="581" y="389" width="83" height="32"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<buttonCell key="cell" type="push" title="Logout" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="BSD-Se-apF">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<action selector="Logout:" target="XfG-lQ-9wD" id="eHM-Jj-e7z"/>
</connections>
</button>
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Q1A-Uy-iY2">
<rect key="frame" x="381" y="335" width="66" height="32"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<buttonCell key="cell" type="push" title="Join" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="KpO-us-tGE">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<action selector="JoinChannel:" target="XfG-lQ-9wD" id="Yvm-jb-ow0"/>
</connections>
</button>
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="uaV-MT-mPj">
<rect key="frame" x="584" y="335" width="76" height="32"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<buttonCell key="cell" type="push" title="Leave" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="dZn-qK-4cK">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<action selector="LeaveChannel:" target="XfG-lQ-9wD" id="MWd-IT-Uip"/>
</connections>
</button>
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="zfe-Ec-M4n">
<rect key="frame" x="587" y="281" width="71" height="32"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<buttonCell key="cell" type="push" title="Send" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="rbh-Vm-cYi">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<action selector="SendGroupMsg:" target="XfG-lQ-9wD" id="pDh-8Z-2mK"/>
</connections>
</button>
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="c09-B2-Vz3">
<rect key="frame" x="587" y="230" width="71" height="32"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<buttonCell key="cell" type="push" title="Send" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="MbO-Qp-1fw">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<action selector="SendPeerMsg:" target="XfG-lQ-9wD" id="6DP-jS-kAU"/>
</connections>
</button>
<textField verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Ykl-lc-LSx">
<rect key="frame" x="489" y="237" width="96" height="28"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" borderStyle="bezel" drawsBackground="YES" id="vqf-ce-X3Z">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="EVS-Pk-gmz">
<rect key="frame" x="513" y="273" width="48" height="16"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" lineBreakMode="clipping" title="Peer ID" id="F09-kd-FIl">
<font key="font" metaFont="system"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<scrollView fixedFrame="YES" borderType="none" horizontalLineScroll="10" horizontalPageScroll="10" verticalLineScroll="10" verticalPageScroll="10" hasHorizontalScroller="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Q8T-ql-eg2">
<rect key="frame" x="12" y="20" width="640" height="209"/>
<autoresizingMask key="autoresizingMask"/>
<clipView key="contentView" drawsBackground="NO" copiesOnScroll="NO" id="SYc-Iw-hu7">
<rect key="frame" x="0.0" y="0.0" width="625" height="209"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<textView importsGraphics="NO" richText="NO" verticallyResizable="YES" spellingCorrection="YES" smartInsertDelete="YES" id="c5T-WT-B0b">
<rect key="frame" x="0.0" y="0.0" width="625" height="209"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="textColor" name="textColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
<size key="minSize" width="625" height="209"/>
<size key="maxSize" width="766" height="10000000"/>
<color key="insertionPointColor" name="textColor" catalog="System" colorSpace="catalog"/>
</textView>
</subviews>
</clipView>
<scroller key="horizontalScroller" hidden="YES" verticalHuggingPriority="750" horizontal="YES" id="XoY-7p-i18">
<rect key="frame" x="-100" y="-100" width="225" height="15"/>
<autoresizingMask key="autoresizingMask"/>
</scroller>
<scroller key="verticalScroller" verticalHuggingPriority="750" horizontal="NO" id="uNS-n6-n8J">
<rect key="frame" x="625" y="0.0" width="15" height="209"/>
<autoresizingMask key="autoresizingMask"/>
</scroller>
</scrollView>
</subviews>
</view>
<connections>
<outlet property="ChannelIDTextField" destination="7zu-6p-vJj" id="VWt-Bh-24b"/>
<outlet property="GroupMsgButton" destination="zfe-Ec-M4n" id="izK-67-iY2"/>
<outlet property="GroupMsgTextField" destination="eZF-Je-F07" id="vK6-i3-788"/>
<outlet property="JoinButton" destination="Q1A-Uy-iY2" id="WxT-j2-kUE"/>
<outlet property="LeaveButton" destination="uaV-MT-mPj" id="QpT-38-W6F"/>
<outlet property="LoginButton" destination="8ld-U7-qEb" id="gtb-XO-CRg"/>
<outlet property="LogoutButton" destination="h2Z-Uu-Bpv" id="OfC-dx-4fM"/>
<outlet property="MsgTextView" destination="Q8T-ql-eg2" id="jnO-2R-T1w"/>
<outlet property="PeerMsgButton" destination="c09-B2-Vz3" id="8aS-cj-N0n"/>
<outlet property="PeerMsgTextField" destination="l5d-LC-xJP" id="XFD-ar-Sm5"/>
<outlet property="UserIDTextField" destination="Vhs-Qx-cHl" id="4ty-Po-1oM"/>
</connections>
</viewController>
<customObject id="rPt-NT-nkU" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="158" y="753"/>
</scene>
</scenes>
</document>
为了帮助你快速实现并理解相关功能,本文通过最简方式,在一个视图里实现以下操作:
ViewController.h
并将内容替换为以下代码://
// ViewController.h
// RtmQuickstart
//
// Created by macoscatalina on 2021/6/10.
// Copyright © 2021 macoscatalina. All rights reserved.
//
#import <Cocoa/Cocoa.h>
#import <AgoraRtmKit/AgoraRtmKit.h>
@interface ViewController : NSViewController
// Buttons
@property (weak, nonatomic) IBOutlet NSButton *LoginButton;
@property (weak, nonatomic) IBOutlet NSButton *LogoutButton;
@property (weak, nonatomic) IBOutlet NSButton *JoinButton;
@property (weak, nonatomic) IBOutlet NSButton *LeaveButton;
@property (weak, nonatomic) IBOutlet NSButton *GroupMsgButton;
@property (weak, nonatomic) IBOutlet NSButton *PeerMsgButton;
// Textfields
@property (weak, nonatomic) IBOutlet NSTextField *UserIDTextField;
@property (weak, nonatomic) IBOutlet NSTextField *ChannelIDTextField;
@property (weak, nonatomic) IBOutlet NSTextField *GroupMsgTextField;
@property (weak, nonatomic) IBOutlet NSTextField *PeerMsgTextField;
@property (weak, nonatomic) IBOutlet NSTextField *PeerIDTextField;
@property (weak) IBOutlet NSScrollView *MsgTextView;
@end
ViewController.m
并将内容替换为以下代码。你需要将 Your_App_ID
替换为你的 App ID; 将 Your_Token
替换为你的 Token。//
// ViewController.m
// RtmQuickstart
//
// Created by macoscatalina on 2021/6/10.
// Copyright © 2021 macoscatalina. All rights reserved.
//
#import "ViewController.h"
@interface ViewController ()<AgoraRtmChannelDelegate, AgoraRtmDelegate>
@property(nonatomic, strong)AgoraRtmKit* kit;
@property(nonatomic, strong)AgoraRtmChannel* channel;
@property(nonatomic, strong)AgoraRtmSendMessageOptions* options;
@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;
@property NSTextView* textView;
- (void)AddMsgToRecord:(NSString*)text;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// 你的 App ID
self.appID = @"Your_App_ID";
// 创建 AgoraRtmKit 实例
_kit = [[AgoraRtmKit alloc] initWithAppId:self.appID delegate:self];
self.textArray = [[NSMutableArray alloc]init];
}
// 将消息记录加入 TextView
- (void)AddMsgToRecord:(NSString*)text {
[self.textArray addObject:(self.text)];
NSSize contentSize = [self.MsgTextView contentSize];
self.textView = [[NSTextView alloc] initWithFrame:NSMakeRect(0, 0, contentSize.height, contentSize.width)];
[self.textView setTextColor:NSColor.blueColor];
[self.textView setString:[self.textArray componentsJoinedByString:(@"\n")]];
[self.MsgTextView setDocumentView:self.textView];
}
// 登录按钮
- (IBAction)Login:(id)sender {
self.uid = [self.UserIDTextField stringValue];
// 你的 Token
self.token = @"Your_Token";
// 登录 RTM 系统
[_kit loginByToken:(self.token) user:(self.uid) completion:^(AgoraRtmLoginErrorCode errorCode) {
if (errorCode != AgoraRtmLoginErrorOk){
self.text = [NSString stringWithFormat:@"Login failed for user %@. Code: %ld",self.uid, (long)errorCode];
NSLog(@"%@", self.text);
}
else {
self.text = [NSString stringWithFormat:@"Login successful for user %@. Code: %ld",self.uid, (long)errorCode];
NSLog(@"%@", self.text);
}
[self AddMsgToRecord:(self.text)];
}
];}
// 登出按钮
- (IBAction)Logout:(id)sender {
// 登出 RTM 系统
[_kit logoutWithCompletion:^(AgoraRtmLogoutErrorCode errorCode) {
if (errorCode == AgoraRtmLogoutErrorOk){
self.text = [NSString stringWithFormat:@"Logout successful. Code: %ld",(long)errorCode];
NSLog(@"%@", self.text);
} else {
self.text = [NSString stringWithFormat:@"Logout failed. Code: %ld",(long)errorCode];
NSLog(@"%@", self.text); }
[self AddMsgToRecord:(self.text)];
}];
}
// 加入频道按钮
- (IBAction)JoinChannel:(id)sender {
self.channelID = [self.ChannelIDTextField stringValue];
// 创建 RTM 频道
_channel = [_kit createChannelWithId:self.channelID delegate:self];
// 加入 RTM 频道
[_channel joinWithCompletion:^(AgoraRtmJoinChannelErrorCode errorCode) {
if(errorCode == AgoraRtmJoinChannelErrorOk){
self.text = [NSString stringWithFormat:@"Successfully joined channel %@ Code: %ld",self.channelID,(long)errorCode];
NSLog(@"%@", self.text);
} else {
self.text = [NSString stringWithFormat:@"Failed to join channel %@ Code: %ld",self.channelID, (long)errorCode];
NSLog(@"%@", self.text); }
[self AddMsgToRecord:(self.text)];
}];
}
-(void)channel:(AgoraRtmChannel *)channel memberLeft:(AgoraRtmMember *)member
{
self.text = [NSString stringWithFormat:@"%@ left channel %@", member.channelId, member.userId];
[self AddMsgToRecord:(self.text)];
}
-(void)channel:(AgoraRtmChannel *)channel memberJoined:(AgoraRtmMember *)member
{
self.text = [NSString stringWithFormat:@"%@ joined channel %@", member.channelId, member.userId];
[self AddMsgToRecord:(self.text)];
}
// 离开频道按钮
- (IBAction)LeaveChannel:(id)sender {
[_channel leaveWithCompletion:^(AgoraRtmLeaveChannelErrorCode errorCode) {
if (errorCode == AgoraRtmLeaveChannelErrorOk){
self.text = [NSString stringWithFormat:@"Leave channel successful Code: %ld", (long)errorCode];
} else {
self.text = [NSString stringWithFormat:@"Failed to leave channel Code: %ld", (long)errorCode]; }
[self AddMsgToRecord:(self.text)];
}];
}
// 发送频道消息按钮
- (IBAction)SendGroupMsg:(id)sender {
self.channelMsg = [self.GroupMsgTextField stringValue];
self.options.enableOfflineMessaging = true;
[_channel sendMessage:[[AgoraRtmMessage alloc] initWithText:self.channelMsg] sendMessageOptions:self.options completion:^(AgoraRtmSendChannelMessageErrorCode errorCode) {
if (errorCode == AgoraRtmSendChannelMessageErrorOk)
{
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)errorCode];
}
[self AddMsgToRecord:(self.text)];
}];
}
// 显示收到的频道消息
- (void)channel:(AgoraRtmChannel *)channel messageReceived:(AgoraRtmMessage *)message fromMember:(AgoraRtmMember *)member
{
self.text = [NSString stringWithFormat:@"Message received in channel: %@ from user: %@ content: %@",member.channelId, member.userId, message.text];
[self AddMsgToRecord:(self.text)];
}
// 发送点对点消息按钮
- (IBAction)SendPeerMsg:(id)sender {
self.peerMsg = [self.PeerMsgTextField stringValue];
self.peerID = [self.PeerIDTextField stringValue];
[_kit sendMessage:[[AgoraRtmMessage alloc] initWithText:self.peerMsg] toPeer:self.peerID completion:^(AgoraRtmSendPeerMessageErrorCode errorCode) {
if (errorCode == AgoraRtmSendPeerMessageErrorOk)
{
self.text = [NSString stringWithFormat:@"Message sent from user: %@ to user: %@ content: %@", self.uid, self.peerID, self.peerMsg];
}
else
{
self.text = [NSString stringWithFormat:@"Message failed to send from user: %@ to user: %@ content: %@ Error: %ld", self.uid, self.peerID, self.peerMsg, (long)errorCode]; }
[self AddMsgToRecord:(self.text)];
}];
}
// 显示收到的点对点消息
- (void)rtmKit:(AgoraRtmKit *)kit messageReceived:(AgoraRtmMessage *)message fromPeer:(NSString*)peerId
{
self.text = [NSString stringWithFormat:@"Message received from user: %@ content: %@", peerId, message.text];
[self AddMsgToRecord:(self.text)];}
// 显示当前用户连接状态变化
- (void)rtmKit:(AgoraRtmKit *)kit connectionStateChanged:(AgoraRtmConnectionState)state reason:(AgoraRtmConnectionChangeReason)reason
{
self.text = [NSString stringWithFormat:@"Connection status changed to: %ld Reason: %ld", (long)state, (long)reason];
[self AddMsgToRecord:(self.text)];
}
- (void)setRepresentedObject:(id)representedObject {
[super setRepresentedObject:representedObject];
// Update the view, if already loaded.
}
@end
编译并在模拟器或真机上运行项目。运行效果如下:
pod init
命令。项目文件夹下会生成一个 Podfile 文本文件。Your App
替换为你的 Target 名称。target 'Your App' do
use_frameworks!
pod 'AgoraRtm_macOS'
end
pod update
命令更新本地库版本。pod install
命令安装 Agora SDK。成功安装后,Terminal 中会显示 Pod installation complete!
,此时项目文件夹下会生成一个 workspace 文件。v1.4.4 及以上版本
AgoraRtmKit.framework
至项目路径下。v1.4.4 以下版本
将 libs 文件夹内的 AgoraRtmKit.framework 文件复制到项目文件夹下。
打开 Xcode,进入 TARGETS > Project Name > Build Phases > Link Binary with Libraries 菜单,点击 + 添加如下库。在添加 AgoraRtmKit.framework 文件时,还需在点击 + 后点击 Add Other…,找到本地文件并打开。
RTM 支持多个相互独立的 AgoraRtmKit 实例。
在收发点对点消息或进行其他频道操作前,请确保你已成功登录 Agora RTM 系统(即确保已经收到 AgoraRtmLoginErrorOk
)。
使用频道核心功能前必须通过调用 createChannelWithId 方法创建频道实例。
你可以创建多个 AgoraRtmKit 客户端实例,但是每个客户端实例最多只能同时加入 20 个频道。每个频道的 channelId
参数应该不同。
当离开了频道且不再加入该频道时,可以调用 destroyChannelWithId 方法及时释放频道实例所占用的资源。
接收到的 AgoraRtmMessage 消息对象不能重复利用再用于消息发送。