标签:
本篇是 即时通信之XMPP(2) 接上次 即时通信之XMPP(1)
// 获取管理好友的单例对象 XMPPRosterCoreDataStorage *rosterStorage = [XMPPRosterCoreDataStorage sharedInstance]; // 给roster属性进行初始化 self.xmppRoster = [[XMPPRoster alloc] initWithRosterStorage:rosterStorage dispatchQueue:dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0)]; // 将好友列表在通道中激活 [self.xmppRoster activate:self.xmppStream]; // 设置花名册代理 [self.xmppRoster addDelegate:self delegateQueue:dispatch_get_main_queue()];
代码:
#pragma mark - XMPPRosterDelegate代理方法 /// 开始获取好友 - (void)xmppRosterDidBeginPopulating:(XMPPRoster *)sender { NSLog(@"开始获取好友"); } /// 结束获取好友 - (void)xmppRosterDidEndPopulating:(XMPPRoster *)sender { // 当前页面适用于显示好友列表的,所以在结束好友获取的代理方法中要进行刷新页面,然后将数据显示 // 刷新页面 [self.tableView reloadData]; } // 接收好友的信息 // 这个代理方法会被执行多次,每添加完好友,相对应的好友信息都要有反馈 - (void)xmppRoster:(XMPPRoster *)sender didReceiveRosterItem:(DDXMLElement *)item { /* both 互为好友 none 互不为好友 to 我已经添加对方为好友,但是对方还没有接受 from 对方已经添加我为好友,但是我还没有接受 remove 曾经删除的好友 */ // 描述自己和对方之间的关系 NSString *description = [[item attributeForName:@"subscription"] stringValue]; NSLog(@"description = %@", description); if ([description isEqualToString:@"to"] || [description isEqualToString:@"none"] || [description isEqualToString:@"both"] || [description isEqualToString:@"from"]) { // 添加好友 // 获取添加好友的JID NSString *friendJID = [[item attributeForName:@"jid"] stringValue]; XMPPJID *jid = [XMPPJID jidWithString:friendJID]; // 如果数组中有这个用户,就不用再进行操作 if ([self.allRosterArray containsObject:jid]) { return; } // 添加好友到数组 [self.allRosterArray addObject:jid]; // 在tableView中添加这条数据 NSIndexPath *indexPath = [NSIndexPath indexPathForItem:self.allRosterArray.count - 1 inSection:0]; [self.tableView insertRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationRight]; } } // 收到好友的监听请求(加好友请求),是否同意 - (void)xmppRoster:(XMPPRoster *)sender didReceivePresenceSubscriptionRequest:(XMPPPresence *)presence { self.fromJID = presence.from; // 需要相关的提醒框去确定是否接受 UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"好友请求" message:@"是否接受好友请求" preferredStyle:UIAlertControllerStyleAlert]; __weak typeof(self)weakSelf = self; UIAlertAction *acceptAction = [UIAlertAction actionWithTitle:@"接受" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { // 在花名册中去接受相关的好友 [[XMPPManager shareXMPPManager].xmppRoster acceptPresenceSubscriptionRequestFrom:weakSelf.fromJID andAddToRoster:YES]; }]; UIAlertAction *rejectAction = [UIAlertAction actionWithTitle:@"拒绝" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { [[XMPPManager shareXMPPManager].xmppRoster rejectPresenceSubscriptionRequestFrom:weakSelf.fromJID]; }]; [alertController addAction:acceptAction]; [alertController addAction:rejectAction]; [self presentViewController:alertController animated:YES completion:nil]; }
代码:
- (void)addFriend { UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"添加好友" message:@"请输入添加好友的名字" preferredStyle:UIAlertControllerStyleAlert]; __weak typeof(self)mySlef = self; [alertController addTextFieldWithConfigurationHandler:^(UITextField * _Nonnull textField) { mySlef.textField = textField; }]; UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) { NSLog(@"取消删除好友!"); }]; UIAlertAction *ensureAction = [UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { // 使用JID记录 XMPPJID *friendJID = [XMPPJID jidWithString:[NSString stringWithFormat:@"%@@%@", mySlef.textField.text, kDomin]]; // 监听好友的动作 [mySlef.xmppRoster subscribePresenceToUser:friendJID]; // 添加好友 [mySlef.xmppRoster addUser:friendJID withNickname:mySlef.textField.text]; }]; [alertController addAction:ensureAction]; [alertController addAction:cancelAction]; [[self getCurrentVC] presentViewController:alertController animated:YES completion:nil]; }
代码:
#pragma mark - 删除好友 - (void)removeFriendWithName:(NSString *)name { // 使用JID记录 XMPPJID *friendJID = [XMPPJID jidWithUser:name domain:kDomin resource:kResource]; // 停止监听好友 [self.xmppRoster unsubscribePresenceFromUser:friendJID]; // 删除好友 [self.xmppRoster removeUser:friendJID]; }
从服务器获取聊天记录,根据数据属性判断消息类型
发送消息
接收消息
// 获取管理消息的存储对象 XMPPMessageArchivingCoreDataStorage *storage = [XMPPMessageArchivingCoreDataStorage sharedInstance]; // 消息管理器的初始化 self.messageArchiving = [[XMPPMessageArchiving alloc] initWithMessageArchivingStorage:storage dispatchQueue:dispatch_get_main_queue()]; // 激活通道 [self.messageArchiving activate:self.xmppStream]; // 设置代理 [self.messageArchiving addDelegate:self delegateQueue:dispatch_get_main_queue()]; // 设置消息管理上下文 self.context = [storage mainThreadManagedObjectContext];
获取聊天记录使用CoreData的方式
创建请求
创建实体描述,实体名: XMPPMessageArchiving_Message_CoreDataObject
创建谓词查询条件,条件:streamBareJidStr == 本人Jid AND bareJidStr == 好友Jid
创建排序对象,排序条件:timestamp
执行请求
代码:
#pragma mark - 显示消息 - (void)showMessage { // 获取管理上下文 NSManagedObjectContext *contxt = [XMPPManager shareXMPPManager].context; // 初始化请求对象 NSFetchRequest *request = [NSFetchRequest new]; // 获取实体 NSEntityDescription *entity = [NSEntityDescription entityForName:@"XMPPMessageArchiving_Message_CoreDataObject" inManagedObjectContext:contxt]; // 设置查询请求的实体 [request setEntity:entity]; // 设置谓词查询 NSPredicate *predicate = [NSPredicate predicateWithFormat:@"streamBareJidStr == %@ AND bareJidStr == %@", [XMPPManager shareXMPPManager].xmppStream.myJID.bare, self.chatToJID.bare]; [request setPredicate:predicate]; // 按照时间顺序排序 NSSortDescriptor *sort = [[NSSortDescriptor alloc] initWithKey:@"timestamp" ascending:YES]; [request setSortDescriptors:@[sort]]; // 执行相关的操作 NSArray *resultArray = [contxt executeFetchRequest:request error:nil]; // 先清空消息数组 [self.allMessageArray removeAllObjects]; // 添加context执行结果数组 [self.allMessageArray addObjectsFromArray:resultArray]; // 刷新UI [self.tableView reloadData]; // 当前聊天记录跳到最后一行 if (self.allMessageArray.count > 0) { NSIndexPath * indexPath = [NSIndexPath indexPathForRow:self.allMessageArray.count-1 inSection:0]; // 跳到最后一行 [self.tableView selectRowAtIndexPath:indexPath animated:YES scrollPosition:UITableViewScrollPositionBottom]; } }
#pragma mark - 发送点击方法 - (void)sendMessageAction { // 设置message的body XMPPMessage *message = [XMPPMessage messageWithType:@"chat" to:self.chatToJID]; // 发送的内容,一般是从输入框获取,这里我们就写成固定的值 [message addBody:@"可以"]; // 通过通道进行消息发送 [[XMPPManager shareXMPPManager].xmppStream sendElement:message]; }
代码:
#pragma mark 发送消息成功 - (void)xmppStream:(XMPPStream *)sender didSendMessage:(XMPPMessage *)message { // 重新显示相关消息 [self showMessage]; } #pragma mark 接受消息成功 - (void)xmppStream:(XMPPStream *)sender didReceiveMessage:(XMPPMessage *)message { [self showMessage]; } #pragma mark 发送消息失败 - (void)xmppStream:(XMPPStream *)sender didFailToSendMessage:(XMPPMessage *)message error:(NSError *)error { NSLog(@"发送消息失败"); }
代码:
//重写message方法,在cell上显示聊天记录 - (void)setMessage:(NSString *)message { if (_message != message) { _message = message; self.contentLabel.text = _message; // self.contentLabel.numberOfLines = 0; [self.contentLabel sizeToFit]; CGRect rect = self.frame; if (self.isOut) {//发出去的 self.backgroundImageView.image = [[UIImage imageNamed:@"chat_to"] stretchableImageWithLeftCapWidth:45 topCapHeight:40]; self.backgroundImageView.frame = CGRectMake(rect.size.width - self.contentLabel.frame.size.width - 50-20, 10, self.contentLabel.frame.size.width+20, rect.size.height-20); }else{//接收的 self.backgroundImageView.image = [[UIImage imageNamed:@"chat_from"] stretchableImageWithLeftCapWidth:45 topCapHeight:40]; self.backgroundImageView.frame = CGRectMake(50, 10,self.contentLabel.frame.size.width+40, rect.size.height-20); } //因为contentLabel已经自适应文字大小,故不用设置宽高,但需要设置位置 self.contentLabel.center = CGPointMake(self.backgroundImageView.frame.size.width/2.0, self.backgroundImageView.frame.size.height/2.0); } }
以上代码均为练习代码的部分代码!完整练习代码github下载地址: https://github.com/AlonerOwl/UISenior11_-_1
由于只是练习代码,对于界面和部分功能没有优化,看起来比较low,如果有需求,请自己进行优化。
代码效果图:
标签:
原文地址:http://www.cnblogs.com/gfxxbk/p/5509583.html