XMPPFramework
1. 导入源码
1). 将下载好的XMPPFramework解压,解压后的目录如下:
2). 将Sample_XMPPFramework.h更名为XMPPFramework.h,然后将XMPPFramework-3.6.4文件夹直接拖入要使用该框架的工程中,然后删除将XMPPFramwork-3.6.4文件夹中的文件夹(除Xcode文件夹)及XMPPFramework.h文件保留,其他文件删除,删除后结构如图3,编译。
3). 解决错误I
解决办法:
- 在Build Settings 搜索Header Search Paths 添加头文件搜索路径:
/usr/include/libxml2
- 在Build Phasses->Link Binary With Libraries中添加两个动态链接库:
libxml2.tbd
、libresolv.tbd
- 在Build Settings 搜索prefix Header,在Prefix Header中添加
$SRCROOT/$(PRODUCT_NAME)/PrefixHeader.pch
- 在项目的根目录下新建pch文件:Other->PCH File。
4). 编译, 报如下错误:
解决办法:
- 在PrefixHeader.pch中添加头文件
#import <UIKit/UIKit.h>
,添加后内容如下:
5). 编译,此时如果不出现意外,就可以成功编译。但我在编译时出现如下错误:
问题原因:重复定义
解决办法:找到对应的位置,将34行注释,因此是重复定义,因此注释之后对源码没有影响。
6). 成功编译
2. 注册与登陆
PrefixHeader.pch
#ifndef PrefixHeader_pch
#define PrefixHeader_pch
#import <UIKit/UIKit.h>
#import "XMPPFramework.h"
#import "MTStreamManager.h"
#endif
MTStreamManager.h
#import <Foundation/Foundation.h>
@interface MTStreamManager : NSObject
typedef NS_ENUM(NSInteger, connectToServer) {
connectToSerLogin, // 登陆
connectToSerRegist // 注册
};
// 单例
+ (instancetype) sharedManager;
// 创建XMPPStream流
@property (nonatomic, strong) XMPPStream *xmppStream;
// 存储密码
@property (nonatomic, copy) NSString *password;
// 区别注册还是登陆
@property (nonatomic) connectToServer connectStatus;
// 注册
- (void) registWithName:(NSString *)name andPassword:(NSString *)password;
// 登陆
- (void) loginWithName:(NSString *)name andPassword:(NSString *)password;
@end
MTStreamManager.m
#import "MTStreamManager.h"
// 打印日志需要
#import "DDLog.h"
#import "DDTTYLogger.h"
#import "XMPPLogging.h"
#define DO_MAIN @"mazaiting.com"
@interface MTStreamManager() <XMPPStreamDelegate>
@end
@implementation MTStreamManager
static MTStreamManager *sInstance;
// 单例
+ (instancetype) sharedManager {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sInstance = [MTStreamManager new];
// 设置日志打印
[DDLog addLogger:[DDTTYLogger sharedInstance]];
// 设置日志等级
[DDLog setLogLevel:XMPP_LOG_FLAG_SEND_RECV forClass:self];
});
return sInstance;
}
// 懒加载XMPPStream
- (XMPPStream *)xmppStream {
if (nil == _xmppStream) {
// 创建
_xmppStream = [[XMPPStream alloc] init];
// 设置属性
// ip
_xmppStream.hostName = @"127.0.0.1";
// 端口
_xmppStream.hostPort = 5222;
// 设置代理--多播代理
[_xmppStream addDelegate:self delegateQueue:dispatch_get_main_queue()];
}
return _xmppStream;
}
// 注册
- (void) registWithName:(NSString *)name andPassword:(NSString *)password {
// 创建一个JID
XMPPJID *jid = [XMPPJID jidWithUser:name domain:DO_MAIN resource:nil];
// 设置MyJID
[self.xmppStream setMyJID:jid];
// 设置密码
self.password = password;
// 设置状态为注册
self.connectStatus = connectToSerRegist;
// 连接到服务器
[self connectServer];
}
// 登陆
- (void) loginWithName:(NSString *)name andPassword:(NSString *)password {
// 创建一个JID
XMPPJID *jid = [XMPPJID jidWithUser:name domain:DO_MAIN resource:nil];
// 设置MyJID
[self.xmppStream setMyJID:jid];
// 设置密码
self.password = password;
// 设置状态为注册
self.connectStatus = connectToSerLogin;
// 连接到服务器
[self connectServer];
}
// 连接到服务器
- (void)connectServer {
// 判断当前是否有连接,如果有则断开
if ([self.xmppStream isConnected]) {
// 退出登陆
[self logout];
}
// 异常信息
NSError *error = nil;
// 连接服务器
[self.xmppStream connectWithTimeout:15.0f error:&error];
// 判断是否连接成功
if (error) {
NSLog(@"连接失败");
}
}
// 退出登陆
- (void) logout {
// 用户状态类
XMPPPresence *presence = [XMPPPresence presenceWithType:@"unavailable"];
// 向服务器发送离线通知
[self.xmppStream sendElement:presence];
// 断开连接
[self.xmppStream disconnect];
}
// 激活其他模块
- (void) activite {
}
#pragma mark 代理方法,连接成功之后回调
- (void)xmppStreamDidConnect:(XMPPStream *)sender {
switch (self.connectStatus) {
case connectToSerLogin:
{
// 错误
NSError *error = nil;
// 登陆
[self.xmppStream authenticateWithPassword:self.password error:&error];
// 匿名登陆
// [self.xmppStream authenticateAnonymously:&error];
// 判断是否登陆成功
if (error) {
NSLog(@"登陆失败");
} else {
NSLog(@"登陆成功");
// 登陆成功之后注册其他模块
[self activite];
}
}
break;
case connectToSerRegist:
{
// 错误
NSError *error = nil;
// 注册
[self.xmppStream registerWithPassword:self.password error:&error];
// 判断是否注册成功
if (error) {
NSLog(@"注册失败");
}
// 注册成功之后断开连接
[self logout];
}
break;
default:
break;
}
}
#pragma mark 代理方法,登陆成功之后告诉服务器我要出席
- (void)xmppStreamDidAuthenticate:(XMPPStream *)sender {
// 如果成功,可以出席
XMPPPresence *presence = [XMPPPresence presence];
// 添加出席状态
[presence addChild:[DDXMLElement elementWithName:@"show" stringValue:@"dnd"]];
[presence addChild:[DDXMLElement elementWithName:@"status" stringValue:@"请勿打扰"]];
// 告诉服务器我要出席
[self.xmppStream sendElement:presence];
}
@end
ViewController.m
#import "ViewController.h"
@interface ViewController ()
// 用户名输入框
@property (weak, nonatomic) IBOutlet UITextField *userName;
// 密码输入框
@property (weak, nonatomic) IBOutlet UITextField *passWord;
@end
@implementation ViewController
// 注册
- (IBAction)regist:(id)sender {
NSString *username = self.userName.text;
NSString *password = self.passWord.text;
[[MTStreamManager sharedManager] registWithName:username andPassword:password];
}
// 登陆
- (IBAction)login:(id)sender {
NSString *username = self.userName.text;
NSString *password = self.passWord.text;
[[MTStreamManager sharedManager] loginWithName:username andPassword:password];
}
@end
注册后可在管理控制台中查看
3. 断线重连
1). 在XMPPFramework.h中添加
// 自动重连
#import "XMPPReconnect.h"
2). 在MTStreamManager.h中添加属性
// 创建自动重连对象
@property (nonatomic, strong) XMPPReconnect *xmppReconnect;
3). 在MTStreamManager.m中懒加载xmppReconnect
// 懒加载断线重连
- (XMPPReconnect *)xmppReconnect {
if (nil == _xmppReconnect) {
// 创建对象
_xmppReconnect = [[XMPPReconnect alloc] initWithDispatchQueue:dispatch_get_main_queue()];
// 设置参数
_xmppReconnect.reconnectTimerInterval = 2;
}
return _xmppReconnect;
}
4). 在XMPPFramework.m中的activite方法中进行激活
// 激活其他模块
- (void) activite {
// 激活断线重连
[self.xmppReconnect activate:self.xmppStream];
}
5). 测试方法
进入管理控制台中,选择会话,把登陆的用户点击右侧的关闭连接将其断开,然后刷新页面,如果成功登陆,则断线重连功能完成。
4. 心跳检测
1). 在XMPPFramework.h中添加
// 心跳检测
#import "XMPPAutoPing.h"
2). 在MTStreamManager.h中添加属性
// 创建心跳检测对象
@property (nonatomic, strong) XMPPAutoPing *xmppAutoPing;
3). 在MTStreamManager.m中懒加载xmppAutoPing
// 心跳检测
- (XMPPAutoPing *)xmppAutoPing {
if (nil == _xmppAutoPing) {
// 创建心跳检测
_xmppAutoPing = [[XMPPAutoPing alloc] initWithDispatchQueue:dispatch_get_main_queue()];
// 设置参数
_xmppAutoPing.pingInterval = 3;
}
return _xmppAutoPing;
}
4). 在XMPPFramework.m中的activite方法中进行激活
// 激活其他模块
- (void) activite {
// 激活断线重连
[self.xmppReconnect activate:self.xmppStream];
// 激活心跳检测
[self.xmppAutoPing activate:self.xmppStream];
}
5). 测试方法
运行程序后查看控制台打印,如果一直在不断的刷新,则证明心跳检测开启。
5. 好友功能模块
1). 在XMPPFramework.h中添加
// 好友角色
#import "XMPPRoster.h"
// 好友存储管理
#import "XMPPRosterCoreDataStorage.h"
// 好友的实体
#import "XMPPUserCoreDataStorageObject.h"
2). 在MTStreamManager.h中添加属性
// 创建好友列表功能模块
@property (nonatomic, strong) XMPPRoster *xmppRoster;
3). 在MTStreamManager.m中懒加载xmppRoster
// 好友列表功能
- (XMPPRoster *)xmppRoster {
if (nil == _xmppRoster) {
// 创建对象
_xmppRoster = [[XMPPRoster alloc] initWithRosterStorage:[XMPPRosterCoreDataStorage sharedInstance] dispatchQueue:dispatch_get_global_queue(0, 0)];
// 设置参数
// 是否自动查找新的好友数据
_xmppRoster.autoFetchRoster = YES;
// 是否自动删除用户存储的数据,不需要
_xmppRoster.autoClearAllUsersAndResources = NO;
// 如果自动接收XMPP,会帮我们做一个加好友的操作,代理方法也不会被调用了
_xmppRoster.autoAcceptKnownPresenceSubscriptionRequests = NO;
//设置代理,,注意让MTStreamManager实现XMPPRosterDelegate协议
[_xmppRoster addDelegate:self delegateQueue:dispatch_get_global_queue(0, 0)];
}
return _xmppRoster;
}
4). 在XMPPFramework.m中的activite方法中进行激活
// 激活其他模块
- (void) activite {
// 激活断线重连
[self.xmppReconnect activate:self.xmppStream];
// 激活心跳检测
[self.xmppAutoPing activate:self.xmppStream];
// 激活好友模块
[self.xmppRoster activate:self.xmppStream];
}
5). 使用
- 使用查询控制器来查询数据
@interface MTContactTableViewController () <NSFetchedResultsControllerDelegate>
// 查询控制器,用来查询好友
@property (nonatomic, strong) NSFetchedResultsController *fetchedResultsController;
// 好友列表数组
@property (nonatomic, strong) NSArray *contactArrs;
@end
@implementation MTContactTableViewController
// 懒加载联系人数组
- (NSArray *)contactArrs {
if (nil == _contactArrs) {
_contactArrs = [NSArray array];
}
return _contactArrs;
}
// 懒加载fetchedResultsController,执行查询操作
- (NSFetchedResultsController *)fetchedResultsController {
if (nil == _fetchedResultsController) {
// 创建一个查询请求
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
// 实体
NSEntityDescription *entity = [NSEntityDescription entityForName:@"XMPPUserCoreDataStorageObject" inManagedObjectContext:[XMPPRosterCoreDataStorage sharedInstance].mainThreadManagedObjectContext];
// 谓词, 查询只有双方都是对方的好友的人
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"subscription = %@", @"both"];
// 排序, 根据jidStr进行升序排列
NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"jidStr" ascending:YES];
// 设置实体
fetchRequest.entity = entity;
// 设置谓词
fetchRequest.predicate = predicate;
// 设置排序
fetchRequest.sortDescriptors = @[sortDescriptor];
// 创建fetchedResultsController对象
_fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:[XMPPRosterCoreDataStorage sharedInstance].mainThreadManagedObjectContext sectionNameKeyPath:nil cacheName:@"contacts"];
// 设置代理, 实现协议NSFetchedResultsControllerDelegate
_fetchedResultsController.delegate = self;
}
return _fetchedResultsController;
}
- (void)viewDidLoad {
[super viewDidLoad];
// 删除CoreData中的缓存
[NSFetchedResultsController deleteCacheWithName:@"contacts"];
// 好友代理设置, 实现XMPPRosterDelegate
[[MTStreamManager sharedManager].xmppRoster addDelegate:self delegateQueue:dispatch_get_global_queue(0, 0)];
// 执行查询操作, 查询到之后将数据保存在了fetchedObjects变量中
[self.fetchedResultsController performFetch:nil];
// 获取到数据
self.contactArrs = self.fetchedResultsController.fetchedObjects;
// 刷新数据
[self.tableView reloadData];
}
}
#pragma mark - NSFetchedResultsController协议
// 当CoreData数据发生变化会调用该代理方法
- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller {
NSLog(@"数据发生改变");
// 最新的列表
self.contactArrs = self.fetchedResultsController.fetchedObjects;
// 刷新数据
[self.tableView reloadData];
}
#pragma mark - Table view data source
// 返回TableView中的条目总数
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return self.contactArrs.count;
}
// 设置TableViewCell的高度
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
return 80.0;
}
// 为TableViewCell赋值
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
// 获取TableViewCell
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Contact_Cell"];
// 获取对应行的联系人数据
XMPPUserCoreDataStorageObject *contact = self.contactArrs[indexPath.row];
// 给Cell赋值
// 设置JID
UILabel *nameLabel = (UILabel *)[cell viewWithTag:1002];
nameLabel.text = contact.jidStr;
return cell;
}
@end
6). 添加删除好友
- 主动申请添加好友
// 创建XMPPJID
XMPPJID *jid = [XMPPJID jidWithUser:@"linghaoyu9" domain:DO_MAIN resource:nil];
// 添加好友
// [[MTStreamManager sharedManager].xmppRoster addUser:jid withNickname:@"加好友"];
[[MTStreamManager sharedManager].xmppRoster subscribePresenceToUser:jid];
- 同意对方的请求
// 创建XMPPJID
XMPPJID *jid = [XMPPJID jidWithUser:@"linghaoyu9" domain:DO_MAIN resource:nil];
// 同意添加对方为好友
[[MTStreamManager sharedManager].xmppRoster acceptPresenceSubscriptionRequestFrom:jid andAddToRoster:YES];
- 删除好友
// 创建XMPPJID
XMPPJID *jid = [XMPPJID jidWithUser:@"linghaoyu9" domain:DO_MAIN resource:nil];
// 删除好友
[[MTStreamManager sharedManager].xmppRoster removeUser:jid];
6. 聊天模块
1). 在XMPPFramework.h中添加
// 聊天模块
#import "XMPPMessageArchiving.h"
// 聊天信息的存储管理
#import "XMPPMessageArchivingCoreDataStorage.h"
// 消息实体
#import "XMPPMessageArchiving_Message_CoreDataObject.h"
// 最近联系人实体
#import "XMPPMessageArchiving_Contact_CoreDataObject.h"
2). 在MTStreamManager.h中添加属性
// 创建聊天功能模块
@property (nonatomic, strong) XMPPMessageArchiving *xmppMessageArchiving;
3). 在MTStreamManager.m中懒加载xmppMessageArchiving
// 消息模块
- (XMPPMessageArchiving *)xmppMessageArchiving {
if (nil == _xmppMessageArchiving) {
// 创建对象
_xmppMessageArchiving = [[XMPPMessageArchiving alloc] initWithMessageArchivingStorage:[XMPPMessageArchivingCoreDataStorage sharedInstance] dispatchQueue:dispatch_get_main_queue()];
}
return _xmppMessageArchiving;
}
4). 在XMPPFramework.m中的activite方法中进行激活
// 激活其他模块
- (void) activite {
// 激活断线重连
[self.xmppReconnect activate:self.xmppStream];
// 激活心跳检测
[self.xmppAutoPing activate:self.xmppStream];
// 激活好友模块
[self.xmppRoster activate:self.xmppStream];
// 激活聊天模块
[self.xmppMessageArchiving activate:self.xmppStream];
}
5). 实现XMPPStreamDelegate协议中的xmppStream:didReceiveMessage:方法, 用来接收消息
- MTStreamManager.m中
// 通过代理接收数据
- (void)xmppStream:(XMPPStream *)sender didReceiveMessage:(XMPPMessage *)message {
NSLog(@"接收到的消息: %@", message.body);
// 发送本地通知,在AppDelegate中接收通知
UILocalNotification *noti = [[UILocalNotification alloc] init];
[noti setAlertBody:[NSString stringWithFormat:@"来自%@ : %@ 消息", message.from, message.body]];
// 设置appicon图标
[noti setApplicationIconBadgeNumber:1];
// 弹出本地通知
[[UIApplication sharedApplication] presentLocalNotificationNow:noti];
}
- AppDelegate.m
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// 需要一个用户通知设置, 用来接收通知
UIUserNotificationSettings *setting = [UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeSound|UIUserNotificationTypeAlert|UIUserNotificationTypeBadge categories:nil];
// 注册
[[UIApplication sharedApplication] registerUserNotificationSettings:setting];
return YES;
}
6). 查询消息
@interface MTChatViewController () <NSFetchedResultsControllerDelegate> {
// 消息列表查询控制器
@property (nonatomic, strong) NSFetchedResultsController *fetchedResultsController;
// 消息数组
@property (nonatomic, strong) NSArray *chatArrs;
}
// -----------------具体实现
// 懒加载数组
- (NSArray *)chatArrs {
if (nil == _chatArrs) {
_chatArrs = [NSArray array];
}
return _chatArrs;
}
// 懒加载fetchedResultsController
- (NSFetchedResultsController *)fetchedResultsController {
if (nil == _fetchedResultsController) {
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"XMPPMessageArchiving_Message_CoreDataObject" inManagedObjectContext:[XMPPMessageArchivingCoreDataStorage sharedInstance].mainThreadManagedObjectContext];
[fetchRequest setEntity:entity];
// Specify criteria for filtering which objects to fetch
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"bareJidStr = %@", self.userJid.bare];
[fetchRequest setPredicate:predicate];
// Specify how the fetched objects should be sorted
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"timestamp" ascending:YES];
[fetchRequest setSortDescriptors:[NSArray arrayWithObjects:sortDescriptor, nil]];
_fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:[XMPPMessageArchivingCoreDataStorage sharedInstance].mainThreadManagedObjectContext sectionNameKeyPath:nil cacheName:@"messages"];
_fetchedResultsController.delegate = self;
}
return _fetchedResultsController;
}
- (void)viewDidLoad {
[super viewDidLoad];
// 清除缓存
[NSFetchedResultsController deleteCacheWithName:@"messages"];
// 查询聊天记录
[self.fetchedResultsController performFetch:nil];
// 数据赋值
self.chatArrs = self.fetchedResultsController.fetchedObjects;
// 刷新
[self.tableView reloadData];
}
7). 发送消息
// 发消息--私聊
XMPPMessage *message = [XMPPMessage messageWithType:@"chat" to:self.userJid];
// 发消息--群聊
// XMPPMessage *message = [XMPPMessage messageWithType:@"group" to:self.userJid];
// 设置消息
[message addBody:self.message.text];
// 发消息
[[MTStreamManager sharedManager].xmppStream sendElement:message];
8). 获取最近联系人
@interface MTRecentlyTableViewController () <NSFetchedResultsControllerDelegate, XMPPvCardAvatarDelegate>
// 控制器查询数据
@property (nonatomic, strong) NSFetchedResultsController *fetchedResultsController;
// 最近联系人数组
@property (nonatomic, strong) NSArray *recentlyArrs;
@end
@implementation MTRecentlyTableViewController
// 懒加载数组
- (NSArray *)recentlyArrs {
if (nil == _recentlyArrs) {
_recentlyArrs = [NSArray array];
}
return _recentlyArrs;
}
// 懒加载控制器
- (NSFetchedResultsController *)fetchedResultsController {
if (nil == _fetchedResultsController) {
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"XMPPMessageArchiving_Contact_CoreDataObject" inManagedObjectContext:[XMPPMessageArchivingCoreDataStorage sharedInstance].mainThreadManagedObjectContext];
[fetchRequest setEntity:entity];
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"mostRecentMessageTimestamp" ascending:NO];
[fetchRequest setSortDescriptors:[NSArray arrayWithObjects:sortDescriptor, nil]];
// 创建控制器
_fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:[XMPPMessageArchivingCoreDataStorage sharedInstance].mainThreadManagedObjectContext sectionNameKeyPath:nil cacheName:@"Recently"];
// 设置代理
_fetchedResultsController.delegate = self;
}
return _fetchedResultsController;
}
// NSFetchedResultsController代理, 当查询的内容发生改变的时候会调用此方法
- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller {
// 数据获取
self.recentlyArrs = self.fetchedResultsController.fetchedObjects;
// 数据刷新
[self.tableView reloadData];
}
- (void)viewDidLoad {
[super viewDidLoad];
// 清楚缓存数据
[NSFetchedResultsController deleteCacheWithName:@"Recently"];
// 数据查询
[self.fetchedResultsController performFetch:nil];
// 数组赋值
self.recentlyArrs = self.fetchedResultsController.fetchedObjects;
// 刷新列表
[self.tableView reloadData];
}
7. 资料模块
1). 在XMPPFramework.h中添加
// 自己个人资料模块
#import "XMPPvCardTempModule.h"
// 个人资料内存存储
#import "XMPPvCardTemp.h"
// 个人资料的存储器,自己和别人
#import "XMPPvCardCoreDataStorage.h"
// 个人资料的实体对象
#import "XMPPvCardCoreDataStorageObject.h"
// 好友的个人资料
#import "XMPPvCardAvatarModule.h"
// 好友个人资料实体对象
#import "XMPPvCardAvatarCoreDataStorageObject.h"
2). 在MTStreamManager.h中添加属性
// 自己个人资料的功能类
@property (nonatomic, strong) XMPPvCardTempModule *xmppvCardTempModule;
// 好友个人资料
@property (nonatomic, strong) XMPPvCardAvatarModule *xmppvCardAvatarModule;
3). 在MTStreamManager.m中懒加载xmppvCardTempModule,xmppvCardAvatarModule
// 自己的个人资料
- (XMPPvCardTempModule *)xmppvCardTempModule {
if (nil == _xmppvCardTempModule) {
// 创建对象
_xmppvCardTempModule = [[XMPPvCardTempModule alloc] initWithvCardStorage:[XMPPvCardCoreDataStorage sharedInstance] dispatchQueue:dispatch_get_main_queue()];
}
return _xmppvCardTempModule;
}
// 指定的用户的个人资料
- (XMPPvCardAvatarModule *)xmppvCardAvatarModule {
if (nil == _xmppvCardAvatarModule) {
// 创建
_xmppvCardAvatarModule = [[XMPPvCardAvatarModule alloc] initWithvCardTempModule:_xmppvCardTempModule dispatchQueue:dispatch_get_main_queue()];
}
return _xmppvCardAvatarModule;
}
4). 在XMPPFramework.m中的activite方法中进行激活
// 激活其他模块
- (void) activite {
// 激活断线重连
[self.xmppReconnect activate:self.xmppStream];
// 激活心跳检测
[self.xmppAutoPing activate:self.xmppStream];
// 激活好友模块
[self.xmppRoster activate:self.xmppStream];
// 激活聊天模块
[self.xmppMessageArchiving activate:self.xmppStream];
// 激活个人资料
[self.xmppvCardTempModule activate:self.xmppStream];
// 好友的个人资料
[self.xmppvCardAvatarModule activate:self.xmppStream];
}
5). 查询用户资料
@interface MTMeTableViewController () <XMPPvCardTempModuleDelegate>
// 头像
@property (weak, nonatomic) IBOutlet UIImageView *icon;
// JID
@property (weak, nonatomic) IBOutlet UILabel *name;
// 昵称
@property (weak, nonatomic) IBOutlet UILabel *nickName;
// 个性签名
@property (weak, nonatomic) IBOutlet UILabel *desc;
// 内存存储个人信息
@property (nonatomic, strong) XMPPvCardTemp *myvCardTemp;
@end
@implementation MTMeTableViewController
// 懒加载获取存储数据
- (XMPPvCardTemp *)myvCardTemp {
if (nil == _myvCardTemp) {
_myvCardTemp = [MTStreamManager sharedManager].xmppvCardTempModule.myvCardTemp;
}
return _myvCardTemp;
}
- (void)viewDidLoad {
[super viewDidLoad];
// 设置代理,需要更新用户资料的界面都要实现这个代理
[[MTStreamManager sharedManager].xmppvCardTempModule addDelegate:self delegateQueue:dispatch_get_main_queue()];
// 设置参数
[self update];
}
// 更新
- (void)update {
// 头像
self.icon.image = [UIImage imageWithData:self.myvCardTemp.photo];
// 名字
self.name.text = [MTStreamManager sharedManager].xmppStream.myJID.bare;
// 昵称
self.nickName.text = self.myvCardTemp.nickname;
// 个性签名
self.desc.text = self.myvCardTemp.description;
}
// 更新,需要更新用户资料的界面都要实现这个代理
- (void)xmppvCardTempModuleDidUpdateMyvCard:(XMPPvCardTempModule *)vCardTempModule {
// 清除之前的内存
self.myvCardTemp = nil;
// 重新赋值最新的数据
[self update];
}
@end
6). 更新头像
// 点击头像时执行的方法
// 选择照片--换头像
- (IBAction)pickerImage:(id)sender {
// 相册
UIImagePickerController *picker = [[UIImagePickerController alloc] init];
// 参数设置
picker.allowsEditing = YES;
// 设置代理
picker.delegate = self;
// 弹出控制器
[self.navigationController presentViewController:picker animated:YES completion:nil];
}
// 选中照片
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary<NSString *,id> *)info {
NSLog(@"info = %@", info);
// 获取图片
UIImage *image = info[UIImagePickerControllerEditedImage];
// 装换为二进制数据
NSData *imageData = UIImageJPEGRepresentation(image, 0.2);
// 内存存储
self.xmppvCardTemp.photo = imageData;
// 数据更新
[[MTStreamManager sharedManager].xmppvCardTempModule updateMyvCardTemp:self.xmppvCardTemp];
// 销毁控制器
[self.navigationController dismissViewControllerAnimated:YES completion:nil];
}
// 取消选中
- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker {
// 销毁控制器
[self.navigationController dismissViewControllerAnimated:YES completion:nil];
}
7). 更新昵称或者个性签名
@interface MTUpdateTableViewController ()
// 信息输入框
@property (weak, nonatomic) IBOutlet UITextField *textMessage;
// 内存存储
@property (nonatomic, strong) XMPPvCardTemp *myvCardTemp;
@end
@implementation MTUpdateTableViewController
// 懒加载
- (XMPPvCardTemp *)myvCardTemp {
if (nil == _myvCardTemp) {
_myvCardTemp = [MTStreamManager sharedManager].xmppvCardTempModule.myvCardTemp;
}
return _myvCardTemp;
}
// 取消按钮
- (IBAction)cancel:(id)sender {
// 关闭当前控制器
[self.navigationController popViewControllerAnimated:YES];
}
// 更新数据
- (IBAction)update:(id)sender {
// 数据更新
if ([self.title isEqualToString:@"昵称"]) {
// 对昵称做更新
self.myvCardTemp.nickname = self.textMessage.text;
} else {
// 对个性签名做更新
self.myvCardTemp.description = self.textMessage.text;
}
// 更新数据
[[MTStreamManager sharedManager].xmppvCardTempModule updateMyvCardTemp:self.myvCardTemp];
// 关闭当前控制器
[self.navigationController popViewControllerAnimated:YES];
}
8. 群聊
1). 在XMPPFramework.h中添加
// 群聊功能类
#import "XMPPMUC.h"
// 聊天室功能类
#import "XMPPRoom.h"
// 数据存储管理
#import "XMPPRoomCoreDataStorage.h"
2). 新建群聊管理类
MTMucRoomManager.h 头文件
@interface MTMucRoomManager : NSObject
// 多用户聊天功能类
@property (nonatomic, strong) XMPPMUC *xmppMuc;
// 聊天室功能类
@property (nonatomic, strong) XMPPRoom *xmppRoom;
// 单例
+ (instancetype)sharedMucRoom;
// 加入或者创建聊天室
- (void)joinOrCreateWithRoomJid:(XMPPJID *)roomJid andNickName:(NSString *)nickName;
@end
MTMucRoomManager.m 实现
@interface MTMucRoomManager () <XMPPMUCDelegate, XMPPRoomDelegate>
// 用来存储聊天室的字典
@property (nonatomic, strong) NSMutableDictionary *roomDict;
@end
@implementation MTMucRoomManager
static MTMucRoomManager *sInstance;
// 单例
+ (instancetype)sharedMucRoom {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sInstance = [MTMucRoomManager new];
});
return sInstance;
}
// 懒加载字典
- (NSMutableDictionary *)roomDict {
if (nil == _roomDict) {
// 创建字典
_roomDict = [NSMutableDictionary dictionary];
}
return _roomDict;
}
// 多用户聊天功能类
- (XMPPMUC *)xmppMuc {
if (nil == _xmppMuc) {
// 创建
_xmppMuc = [[XMPPMUC alloc] initWithDispatchQueue:dispatch_get_main_queue()];
// 设置代理
[_xmppMuc addDelegate:self delegateQueue:dispatch_get_main_queue()];
// 激活
[_xmppMuc activate:[MTStreamManager sharedManager].xmppStream];
}
return _xmppMuc;
}
// 聊天室功能类
- (XMPPRoom *)xmppRoom {
if (nil == _xmppRoom) {
// 创建对象
_xmppRoom = [[XMPPRoom alloc] initWithDispatchQueue:dispatch_get_main_queue()];
}
return _xmppRoom;
}
// 加入或者创建聊天室
- (void)joinOrCreateWithRoomJid:(XMPPJID *)roomJid andNickName:(NSString *)nickName {
// 创建房间
XMPPRoom *room = [[XMPPRoom alloc] initWithRoomStorage:[XMPPRoomCoreDataStorage sharedInstance] jid:roomJid dispatchQueue:dispatch_get_main_queue()];
// 激活
[room activate:[MTStreamManager sharedManager].xmppStream];
// 存放在字典中
self.roomDict[roomJid] = room;
// 加入房间
[room joinRoomUsingNickname:nickName history:nil];
// 设置代理
[room addDelegate:self delegateQueue:dispatch_get_main_queue()];
}
#pragma mark 回调
// 加入
- (void)xmppRoomDidJoin:(XMPPRoom *)sender {
// 对房间进行配置
[sender configureRoomUsingOptions:nil];
// 测试方法--需先要在控制台中创建分组与房间
XMPPJID *jid = [XMPPJID jidWithUser:@"linghaoyu9" domain:DO_MAIN resource:nil];
// 邀请加入
[sender inviteUser:jid withMessage:@"来聊天"];
}
// 创建
- (void)xmppRoomDidCreate:(XMPPRoom *)sender {
}
@end
3). 加入聊天室
XMPPJID *jid = [XMPPJID jidWithUser:@"love" domain:@"tochat.mazaiting.com" resource:nil];
// 加入到房间
[[MTMucRoomManager sharedMucRoom] joinOrCreateWithRoomJid:jid andNickName:@"小鱼"];
4). 测试
-
需要先在控制台中创建分组
-
其次在控制台中创建分组
- 完成发消息