本人有若干成套学习视频, 可试看! 可试看! 可试看, 重要的事情说三遍 包含Java
, 数据结构与算法
, iOS
, 安卓
, python
, flutter
等等, 如有需要, 联系微信tsaievan
.
XMPP 为我们提供了花名册模块, 即 XMPPRoster, 如果我们要写一个 APP, 用到花名册模块, 我们就必须添加这个模块,
这个模块的作用就是创建一个花名册的模型对象, 这个模型对象是基于 coreData 框架的,这样,我们就可以利用模型管理上下文给存储调度器发指令, 让存储调度器负责模型的存储.
我们将这个模块在 xmppStream 中激活之后, 那么所有关于presence 和 iq 的节点都会转化成花名册对象存储在沙盒中.
然后控制器获取数据之后就能在 View 上展示出来
- 首先, 我们为 XMPPManager 创建一个分类, 即花名册分类, 在这个分类的方法中我们做三件事情
1.初始化花名册模块
2.为花名册模块设置属性及代理
3.在 xmppStream 中激活花名册模块
YFXMPP+ Roster 分类
#pragma mark *** 添加花名册模块 ***
- (void)addRosterModule
{
/* 1. 初始化 */
self.xmppRoster = [[XMPPRoster alloc]initWithRosterStorage:[XMPPRosterCoreDataStorage sharedInstance] dispatchQueue:dispatch_get_main_queue()];
/* 2. 配置属性 */
/* 自动接收别人添加好友的请求 */
self.xmppRoster.autoAcceptKnownPresenceSubscriptionRequests = YES;
/* 当 xmpp 流断开时,自动清除花名册资源 */
self.xmppRoster.autoClearAllUsersAndResources = YES;
/* 自动查询花名册 */
self.xmppRoster.autoFetchRoster = YES;
/* 3. 设置代理 */
[self.xmppRoster addDelegate:self delegateQueue:dispatch_get_main_queue()];
/* 4. 激活 */
[self.xmppRoster activate:self.xmppstream];
/* 5. 手动获取花名册列表 */
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[self.xmppRoster fetchRoster];
});
}
这样,我在 xmppStream 懒加载之后就添加成功了花名册模块,一旦 xmppStream 流中返回了添加好友, 或者好友关系变更等信息时, 就会走XMPPRosterDelegate 代理 API 回调
#pragma mark *** XMPPRosterDelegate 代理 API 回调 ***
/* 开始获取花名册 */
- (void)xmppRosterDidBeginPopulating:(XMPPRoster *)sender withVersion:(NSString *)version
{
}
/* 结束获取花名册 */
- (void)xmppRosterDidEndPopulating:(XMPPRoster *)sender
{
}
/* 接收到好友请求 */
- (void)xmppRoster:(XMPPRoster *)sender didReceivePresenceSubscriptionRequest:(XMPPPresence *)presence
{
if (self.rosterReceiveBlock) {
self.rosterReceiveBlock(presence);
}
}
/* 获取到每一个花名册好友 */
- (void)xmppRoster:(XMPPRoster *)sender didReceiveRosterItem:(DDXMLElement *)item
{
}
/* 好友关系变更 */
- (void)xmppRoster:(XMPPRoster *)sender didReceiveRosterPush:(XMPPIQ *)iq
{
if (self.rosterChangeBlock) {
self.rosterChangeBlock(iq);
}
}
如以上代码所示, 在接收到好友请求或者好友关系变更时, 在这个代理方法里我可以完成一个 block 回调, 在这个 block 中,去完成 fetchResultsController的 performFetch, 这样就能够实时拿到最新的数据
联系人控制器的代码
#pragma mark *** 视图的生命周期 ***
- (void)viewDidLoad {
[super viewDidLoad];
self.hidesBottomBarWhenPushed = YES;
__weak typeof(self)weakSelf = self;
kYFXMPPManager.rosterReceiveBlock = ^(XMPPPresence *presence){
[kYFXMPPManager.xmppRoster acceptPresenceSubscriptionRequestFrom:presence.from andAddToRoster:YES];
[weakSelf updateData];
};
kYFXMPPManager.rosterChangeBlock = ^(XMPPIQ *iq){
[weakSelf updateData];
};
}
// -------- 更新数据 --------
- (void)updateData
{
/* 养成良好的习惯, 在 block 之前将 self 转化成 weakSelf, 避免循环引用 */
__weak typeof(self)weakSelf = self;
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[weakSelf.fetchResultsController performFetch:nil];
});
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[weakSelf.tableView reloadData];
});
}
可以看出, 在更新数据的操作里, 我们先去获取数据,然后刷新 tableView
当然这一切都有依赖于NSFetchedResultsController这个神器
#pragma mark *** Getter & Setter ***
- (NSFetchedResultsController *)fetchResultsController
{
if (!_fetchResultsController) {
/* 1. 创建查询请求 */
NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:@"XMPPUserCoreDataStorageObject"];
/* 2. 设置查询请求的属性 */
/* note: 设置排序器,否则程序会崩溃 */
fetchRequest.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"jidStr" ascending:YES]];
/* 设置好友关系为 both */
fetchRequest.predicate = [NSPredicate predicateWithFormat:@"subscription == 'both'"];
/**
* 第一个参数:查询请求
* 第二个参数:管理对象上下文
* 第三个参数:分组依据
* 第四个参数:缓存名字
*/
_fetchResultsController = [[NSFetchedResultsController alloc]initWithFetchRequest: fetchRequest managedObjectContext:[XMPPRosterCoreDataStorage sharedInstance].mainThreadManagedObjectContext sectionNameKeyPath:@"sectionName" cacheName:nil];
/* 3. 执行查询 */
[_fetchResultsController performFetch:nil];
// /* 4. 控制台输出查询结果 */
// for (XMPPUserCoreDataStorageObject *objc in self.fetchResultsController.fetchedObjects) {
// NSLog(@"%@",objc);
// }
/* 5. 刷新 tableView */
[self.tableView reloadData];
}
return _fetchResultsController;
}
当NSFetchedResultsController获取到数据之后, 展示数据就不是什么难事了. 花名册就很容易做出来了.