即时通信2 好友列表 聊天信息
学了cocoaPods,尝试使用它添加第三方的XMPPFramework
(1) 写好podfile:
platform:ios,'8.0'
pod 'XMPPFramework', '~> 3.6.6'
(2) 安装,pod install
(3) 通过.xcworkspace打开工程
这样就直接可以用了,比之前的配置简单了很多
一、获取好友列表
这篇内容与上篇相关,首先在XMPPTool.m中添加一个方法,用来激活模块,当连接成功后调用这个方法。
//激活相关的模块 -(void) activeModules { //1.花名册存储对象 self.rosterStorage = [XMPPRosterCoreDataStorage sharedInstance]; //2.花名册模块 self.rosterModule = [[XMPPRoster alloc] initWithRosterStorage:self.rosterStorage]; //3.激活此模块 [self.rosterModule activate:self.myStream]; //4.添加roster代理 [self.rosterModule addDelegate:self delegateQueue:dispatch_get_main_queue()]; // //1.消息存储对象 // self.msgStorage = [XMPPMessageArchivingCoreDataStorage sharedInstance]; // self.msgModule = [[XMPPMessageArchiving alloc] initWithMessageArchivingStorage:self.msgStorage]; // [self.msgModule activate:self.xmppStream]; // [self.msgModule addDelegate:self delegateQueue:dispatch_get_main_queue()]; }
然后写上搜索好友列表的方法
//查询好友的方法 -(void)getFriends { //查询预备工作,context request,entity NSManagedObjectContext *context = _rosterStorage.mainThreadManagedObjectContext; NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init]; NSEntityDescription *entity = [NSEntityDescription entityForName:@"XMPPUserCoreDataStorageObject" inManagedObjectContext:context]; [fetchRequest setEntity:entity]; //查询条件 //筛选本用户的好友 NSString *userinfo = [NSString stringWithFormat:@"%@@127.0.0.1",self.userName]; NSPredicate *predicate = [NSPredicate predicateWithFormat:@"streamBareJidStr = %@",userinfo]; [fetchRequest setPredicate:predicate]; //排序 NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"displayName"ascending:YES]; [fetchRequest setSortDescriptors:[NSArray arrayWithObjects:sortDescriptor, nil]]; NSError *error = nil; //执行查询获得结果 NSArray *fetchedObjects = [context executeFetchRequest:fetchRequest error:&error]; //输出所有好友的名字 for (XMPPUserCoreDataStorageObject *item in fetchedObjects) { NSString *name = item.displayName; NSLog(@"name = %@",name); } }
还可以通过代理的方法获得用户的好友,导入XMPPRosterDelegate
问题的关键是这些代理方法执行的时间,在登录成功的代理执行之后
#pragma mark -- 好友列表协议方法 -(void)xmppRosterDidBeginPopulating:(XMPPRoster *)sender withVersion:(NSString *)version { NSLog(@"开始获取好友列表"); //这里对本地的用户数组进行判断,如果有残留的信息,应该清空 if (self.allUserInfoArray.count > 0) { [self.allUserInfoArray removeAllObjects]; } } //获取所有好友,有多少好友,这个代理方法执行几遍 -(void)xmppRoster:(XMPPRoster *)sender didReceiveRosterItem:(DDXMLElement *)item { //得到item的jid NSString *jid = [[item attributeForName:@"jid"]stringValue]; //转换成XMPPJID类型 XMPPJID *userJID = [XMPPJID jidWithString:jid]; NSLog(@"%@",[userJID user]); //将所有userJID放入数组,以便在获取好友列表结束时为外部传值 [self.allUserInfoArray addObject:userJID]; } //登录成功后会执行这个代理 -(void)xmppRosterDidEndPopulating:(XMPPRoster *)sender { NSLog(@"获取好友列表结束,此处向外部传值"); self.userListB(_allUserInfoArray); }
把好友显示在TableView上就不说了
二、聊天信息
首先是发送接收消息相关的方法,在这里组装好xml格式的消息,再发送消息
jid的内容大概是这个格式[email protected]
#pragma mark -- 聊天相关 //发送消息方法 -(void)sendMessage:(NSString *)sendMsg toJid:(XMPPJID *)jid { //组装xml格式的消息 XMPPMessage *msg = [XMPPMessage messageWithType:@"chat" to:jid]; /*添加内容节点 <message type = "chat" ,ToJID = toJid> <body>sendMsg</body> </message> */ [msg addBody:sendMsg]; //发送 [self.myStream sendElement:msg]; }下面是代理方法
#pragma mark -- 消息代理方法 -(void)xmppStream:(XMPPStream *)sender didSendMessage:(XMPPMessage *)message { NSLog(@"发送消息成功"); } -(void)xmppStream:(XMPPStream *)sender didFailToSendMessage:(XMPPMessage *)message error:(NSError *)error { NSLog(@"发送失败"); } //接收到消息触发 -(void)xmppStream:(XMPPStream *)sender didReceiveMessage:(XMPPMessage *)message { NSLog(@"接收到消息--%@",[[message attributeForName:@"body"]stringValue]); }
再写获得聊天信息的方法,同样是在数据库进行查找
#pragma mark -- 查询消息记录 -(void)getChatMsgMethod { //初始化聊天记录的存储器 XMPPMessageArchivingCoreDataStorage *storage = [XMPPMessageArchivingCoreDataStorage sharedInstance]; //初始化归档对象,归档对象从服务器获取聊天记录,再存进storage XMPPMessageArchiving *archiving = [[XMPPMessageArchiving alloc]initWithMessageArchivingStorage:storage]; //在通道中激活 [archiving activate:_myStream]; //获得上下文 NSManagedObjectContext *context = storage.mainThreadManagedObjectContext; //查询 NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init]; NSEntityDescription *entity = [NSEntityDescription entityForName:@"XMPPMessageArchiving_Message_CoreDataObject" inManagedObjectContext:context]; [fetchRequest setEntity:entity]; //获取本人的Jid对象 XMPPJID *mineJid = [XMPPJID jidWithUser:self.userName domain:@"127.0.0.1" resource:nil]; //聊天双方的Jid满足条件 NSPredicate *predicate = [NSPredicate predicateWithFormat:@"streamBareJidStr == %@ AND bareJidStr == %@", mineJid,_friendJid]; [fetchRequest setPredicate:predicate]; //根据时间排序 NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"timestamp" ascending:YES]; [fetchRequest setSortDescriptors:[NSArray arrayWithObjects:sortDescriptor, nil]]; NSError *error = nil; NSArray *fetchedObjects = [context executeFetchRequest:fetchRequest error:&error]; if (fetchedObjects.count < 1) { NSLog(@"no chat"); } else { //遍历输出聊天信息 for (int i = 0; i<fetchedObjects.count; i++) { XMPPMessageArchiving_Message_CoreDataObject *object = [fetchedObjects objectAtIndex:i]; //消息内容 NSString *msg = object.body; //发送人 NSString *name = object.bareJidStr; //发送时间 NSDate *timeStamp = object.timestamp; NSLog(@"%@--%@--%@",msg,name,timeStamp); } } }
完成了,fk,通过spark登录的用户,可以接收到模拟器发出的消息,但是spark给模拟器发送消息,触发不了相应的代理方法,查询聊天记录时只能看到模拟器发是消息
另一方面,每个工程虽然用一样的用户名和密码登录,但是各自发出的消息和查看到的聊天记录却是各自独立的。可能每个工程是自己独立的CoreData
还有会话气泡(根据文字自适应长度)和语音图片的问题,有空了再了解