xmpp整理笔记:聊天信息的发送与显示
任何一个信息的发送都需要关注两个部分,信息的发出,和信息在界面中的显示
往期回顾:
xmpp整理笔记:环境的快速配置(附安装包) http://www.cnblogs.com/zhonghuaxiaodangjia/p/4323460.html
xmpp整理笔记:xmppFramework框架的导入和介绍 http://www.cnblogs.com/zhonghuaxiaodangjia/p/4323475.html
xmpp整理笔记:用户网络连接及好友管理 http://www.cnblogs.com/zhonghuaxiaodangjia/p/4323505.html
需要注意一点:
聊天界面输入框并不是textField而是textView,因为textView可以控制多行信息间的上下滚动编辑,如果微信下面的聊天框用的是普通的textField你可以想象会出现什么情况。
用模拟器程序和小鸭子聊天效果图如下:
一。信息的发送
首先要有一个结果调度器
这是通过coredata从SQLlite取数据的必要操作。所有代码写在这个懒加载中
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
- ( NSFetchedResultsController *)fetchedResultsController { // 推荐写法,减少嵌套的层次 if (_fetchedResultsController != nil ) { return _fetchedResultsController; } // 先确定需要用到哪个实体 NSFetchRequest *request = [ NSFetchRequest fetchRequestWithEntityName:@ "XMPPMessageArchiving_Message_CoreDataObject" ]; // 排序 NSSortDescriptor *sort = [ NSSortDescriptor sortDescriptorWithKey:@ "timestamp" ascending: YES ]; request.sortDescriptors = @[sort]; // 每一个聊天界面,只关心聊天对象的消息 request.predicate = [ NSPredicate predicateWithFormat:@ "bareJidStr = %@" , self .chatJID.bare]; // 从自己写的工具类里的属性中得到上下文 NSManagedObjectContext *ctx = [SXXMPPTools sharedXMPPTools].xmppMessageArchivingCoreDataStorage.mainThreadManagedObjectContext; // 实例化,里面要填上上面的各种参数 _fetchedResultsController = [[ NSFetchedResultsController alloc] initWithFetchRequest:request managedObjectContext:ctx sectionNameKeyPath: nil cacheName: nil ]; _fetchedResultsController.delegate = self ; return _fetchedResultsController; } |
写完了结果调度器之后要切记在viewdidload页面首次加载中加上一句,否则不干活
1
2
|
// 查询数据 [ self .fetchedResultsController performFetch: NULL ]; |
发送出消息
因为textView里面没有类似textField的shouldReturn的方法 直接发送信息
所以只能对textView的《代理方法之文本改变方法》 稍加处理达到文本发送的目的
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
#pragma mark - ******************** textView代理方法 - ( BOOL )textView:(UITextView *)textView shouldChangeTextInRange:( NSRange )range replacementText:( NSString *)text { // 判断按下的是不是回车键。 if ([text isEqualToString:@ "
" ]) { // 自定义的信息发送方法,传入字符串直接发出去。 [ self sendMessage:textView.text]; self .textView.text = nil ; return NO ; } return YES ; } |
在输入时如果按下回车键那触发代理方法传入的这个字符就是" " 就会调用自己写的 这个sendMessage方法,传入一个字符串直接发出去。
这个方法内部把传入的文本先addBody 再用自己手写的单例类的xmpp流 发出去。
1
2
3
4
5
6
7
8
9
10
|
#pragma mark - ******************** 发送消息方法 /** 发送信息 */ - ( void )sendMessage:( NSString *)message { XMPPMessage *msg = [XMPPMessage messageWithType:@ "chat" to: self .chatJID]; [msg addBody:message]; [[SXXMPPTools sharedXMPPTools].xmppStream sendElement:msg]; } |
二。信息在tableView中的显示
是在tableView的数据源方法中,先从数据库中取出当前的信息,再判断是发出去的还是接收的。取到不同的可重用标识符,然后赋值
1
2
3
4
5
6
|
// 取出当前行的消息 XMPPMessageArchiving_Message_CoreDataObject *message = [ self .fetchedResultsController objectAtIndexPath:indexPath]; // 判断是发出消息还是接收消息 NSString *ID = ([message.outgoing intValue] == 1) ? @ "SendCell" : @ "ReciveCell" ; SXChatCell *cell = [tableview dequeueReusableCellWithIdentifier:ID]; cell.messageLabel.text = message.body; |
其中sx开的的类名都是我自定义的类,里面都是常规写法。
关于上面提到的工具类SXXmppTools里 这个模块需要用到得属性和方法有
1
2
3
4
5
6
7
8
9
|
/** xmpp流 */ @property ( nonatomic ,strong, readonly ) XMPPStream * xmppStream; /** 消息归档 */ @property ( nonatomic , strong, readonly ) XMPPMessageArchiving *xmppMessageArchiving; /** 消息归档存储 */ @property ( nonatomic , strong, readonly ) XMPPMessageArchivingCoreDataStorage *xmppMessageArchivingCoreDataStorage; + (instancetype)sharedXMPPTools; |
这里有一点需要注意,
因为默认情况下你一进入一位好友的聊天页面,你和所有好友的聊天记录都会显示。因为都是存在同一个数据表里的啊,因此需要做一层过滤,就是懒加载中的这行代码
1
2
|
// 每一个聊天界面,只关心聊天对象的消息 request.predicate = [ NSPredicate predicateWithFormat:@ "bareJidStr = %@" , self .chatJID.bare];
|