其实,网上基于XMPP的iOS聊天客户端例子已经很多了,大多数是基于XMPPFramework进行二次开发的,小弟的也不例外,那为啥要有这篇教程呢?
因为目前网上的教程,大多数只有一个主体功能的实现,一些细节方面不完善,或者没说到。小弟在制作的过程中吃了不少苦头,为了以后的兄弟少走弯路,希望在这里可以跟大家多多交流。PS:小弟iOS开发时间不长,如有错误请大家不吝指教。
声明一下,此教程主要是针对原生Openfire提供的XMPP支持来做的,暂不考虑在服务器端增加任何自编写插件实现扩展功能。当然,在这个系列的完结后,我会开一个系列粗述关于插件的开发,这是后话。我在这里要做的,是手把手跟大家一起做一个达到上线标准的聊天程序客户端,也就是各种细节功能都实现(包括表情、语音、图片等收发)!
入正题,安装Openfire,配置等等的,小弟就不再详述了。一些基本的知识,请大家参考一下这些大大的系列文章
http://blog.csdn.net/acorld/article/category/1584273
http://www.cnblogs.com/dyingbleed/category/467219.html
当把XMPPFramework引入到自己新建的项目时,它原本已经实现了登录和查看好友列表的功能。好,我们可以加上在列表中查看该好友的详细信息。XMPP保存好友的详细信息是使用vCard的,所以,假设点击好友列表中的cell就进入好友详细信息页,我们可以在加入以下代码
- - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
- {
- XMPPUserCoreDataStorageObject *user = [[self fetchedResultsController] objectAtIndexPath:indexPath];
- ChatViewController *controller=[[ChatViewController alloc] init];
- controller.jidStr=user.jidStr;
- [self.navigationController pushViewController:controller animated:YES];
- }
我们暂时用ChatViewController来存放好友信息。
在这里,我们把vCard的信息读出来
- XMPPvCardCoreDataStorage *xmppvCardStorage = [XMPPvCardCoreDataStorage sharedInstance];
- XMPPvCardTempModule *xmppvCardTempModule = [[XMPPvCardTempModule alloc] initWithvCardStorage:xmppvCardStorage];
- XMPPvCardTemp *xmppvCardTemp =[xmppvCardTempModule vCardTempForJID:jid shouldFetch:YES];
然后xmppvcardTemp.nickname就是昵称,如此类推。
等等,为何性别、email、生日等的无法获取呢?
XMPPFramework不知道为什么少了这部分内容的解析,在XMPPvCardTemp.h加上
- @property (nonatomic, strong) NSString *sex;
- @property (nonatomic, strong) NSString *email;
- @property (nonatomic, strong) NSString *birthDay;
在.m文件加上
- - (NSString *)sex {
- return [[self elementForName:@"SEX"] stringValue];
- }
- - (void)setSex:(NSString *)sex {
- XMPP_VCARD_SET_STRING_CHILD(sex, @"SEX");
- }
- - (NSString *)email {
- return [[self elementForName:@"EMAIL"] stringValue];
- }
- - (void)setEmail:(NSString *)email {
- XMPP_VCARD_SET_STRING_CHILD(email, @"EMAIL");
- }
- - (NSString *)birthDay {
- return [[self elementForName:@"BDAY"] stringValue];
- }
- - (void)setBirthDay:(NSString *)birthDay {
- XMPP_VCARD_SET_STRING_CHILD(birthDay, @"BDAY");
- }
嘿,看看xmppvcardTemp.sex,是不是出来了?
至于其他的节点可能还有漏的,可以参照这个完整节点
- <iq from='juliet@capulet.com'
- to='romeo@montague.net/orchard'
- type='result'
- id='vc2'>
- <vCard xmlns='vcard-temp'>
- <BDAY>1476-06-09</BDAY>
- <ADR>
- <CTRY>Italy</CTRY>
- <LOCALITY>Verona</LOCALITY>
- <HOME/>
- </ADR>
- <NICKNAME/>
- <N><GIVEN>Juliet</GIVEN><FAMILY>Capulet</FAMILY></N>
- <EMAIL>jcapulet@shakespeare.lit</EMAIL>
- <PHOTO>
- <TYPE>image/jpeg</TYPE>
- <BINVAL>
- Base64-encoded-avatar-file-here!
- </BINVAL>
- </PHOTO>
- </vCard>
- </iq>
看看你想要用哪个节点,如此类推加上就可。
好了,如何进行资料修改?这个很简单,例如我要修改url,可以这样
- xmppvCardTemp.url=@"csdn.net";
- [self updatePhoto];
- [xmppvCardTempModule updateMyvCardTemp:xmppvCardTemp];
嗯,当然还有头像修改啦,模拟一个IQ发过去就可以了
- NSXMLElement *vCardXML = [NSXMLElement elementWithName:@"vCard" xmlns:
- @"vcard-temp"];
- NSXMLElement *photoXML = [NSXMLElement elementWithName:@"PHOTO"];
- NSXMLElement *typeXML = [NSXMLElement elementWithName:@"TYPE"
- stringValue:@"image/jpeg"];
- UIImage *image=[UIImage imageNamed:@"DefaultPerson.png"];
- NSData *dataFromImage =UIImagePNGRepresentation(image);
- //UIImageJPEGRepresentation(image, 0.7f);
- NSXMLElement *binvalXML = [NSXMLElement elementWithName:@"BINVAL"
- stringValue:[dataFromImage base64EncodedStringWithOptions:NSDataBase64Encoding64CharacterLineLength]];
- [photoXML addChild:typeXML];
- [photoXML addChild:binvalXML];
- [vCardXML addChild:photoXML];
- XMPPvCardTemp *myvCardTemp = [[[self appDelegate] xmppvCardTempModule]
- myvCardTemp];
- if (myvCardTemp) {
- [myvCardTemp setPhoto:dataFromImage];
- [[[self appDelegate] xmppvCardTempModule] updateMyvCardTemp
- :myvCardTemp];
- }
- else{
- XMPPvCardTemp *newvCardTemp = [XMPPvCardTemp vCardTempFromElement
- :vCardXML];
- [[[self appDelegate] xmppvCardTempModule] updateMyvCardTemp
- :newvCardTemp];
- }
好吧,夜深了,今天先讲到这,下回继续。如有问题,欢迎大家留言!