XMPPFramework开发(三):好友列表

</br>

搞事前言


前同一篇博客,我们对XMPPFramework的登录注册功能跟逻辑做了详细的印证,用户登录成功之后,我们需要开的饶是收获到手上账号的至交列表和个人信息,今天及时同样篇博客就是对准忘年交列表的有关逻辑和代理方来举行一下教授说明.我们先瞧SDChat中的好友列表示意图.

</br>

XMPPFramework中好友关系说明解释


当XMPPFramework中呢,好友关系是好透过订阅来促成之,也就是说A与B相互订阅,那么A与B就是忘年交了,如果A只是订阅了B,B没有订阅A,那么我们即便说A与B两者不是好友,当然矣,我以实质上过程中整好友添加的逻辑还是比多之,这里要了解A与B相互订阅(openfire服务器中订阅状态为both,当然矣,订阅状态也起from和to,这样的呢终究好友.具体情况后面会详细说明),那么A与B就是忘年交这一个逻辑即可.

</br>

好友列表获取流程.


当用户登录成功后,我们举行的无限重点的一个模块就是加载好友列表模块.那么好友加载模块的完好流程是什么样的也罢?我们先看一个SDChat好友列表的流程图,帮助我们熟悉好友列表在实际上过程遭到如何呈现的.(图片或看不清楚,请自行下载查看,谢谢.)

</br>

知音服务器数据获得代码有

XMPPFramework中好友列表的军事管制核心类是XMPPRoster,这个仿佛可据此来对忘年交的信获得,添加,删除等操作.在SDChat中,我们拿XMPPRoster声明为SDXmppManager的一个特性对象,并且于初始化过程遭到激活好友模块.代码如下所示.(说明:XMPPRosterCoreDataStorage对象下存储好友数据的.)

self.rosterCoreDataStorage= [XMPPRosterCoreDataStorage sharedInstance];

self.roster = [[XMPPRoster alloc]initWithRosterStorage:self.rosterCoreDataStorage dispatchQueue:dispatch_get_global_queue(0, 0)];

//激活roster
[self.roster activate:self.stream];

实际好友获取是有有限栽方法的,骚栋使用的是代理方获得好友节点的.由于代理方默认的是以登录成功以后默认就见面调用获取好友节点,但是本人开页面的当儿用调剂一下好友节点获取之机,所以,我虽把XMPPRoster的全自动获得好友节点功能关闭了.当然矣,你得用自动取取.这个需要基于实际情况要得,实现代码如下所示.

self.roster.autoFetchRoster = NO;

诸如此类以咱们登录就后,我们需要在- (void)xmppStreamDidAuthenticate:(XMPPStream *)sender是主意被手动调起得好友的方法.调起计吧异常简单,只需要一行代码就可以.

[[SDXmppManager defaulManager].roster fetchRoster];

当我们调起了得到好友的法子后,我们需要在以维系人列表(SDContactsVC)这个控制器中先期安装XMPPRoster目标的代理.我是以初始化就安装了代办对象.

[[SDXmppManager defaulManager].roster addDelegate:self delegateQueue:dispatch_get_main_queue()];

安装好之后代理方其实总共是发出三只底,三独代理调取的其实分别是有所好友节点获取开始,每一个好友节点获取到之时光,所有好友节点获取成功之后,我们得以依据实际状况来开展不同之操作.比如我们在获开始之前初始化好友节点数组,获取了刷新页面等等,具体的老三独代理方如下所示.

//开始获取好友节点列表的时候
-(void)xmppRosterDidBeginPopulating:(XMPPRoster *)sender;

//获取每一个好友节点的时候
-(void)xmppRoster:(XMPPRoster *)sender didReceiveRosterItem:(DDXMLElement *)item;

//结束获取好友节点列表的时候
-(void)xmppRosterDidEndPopulating:(XMPPRoster *)sender;

即时是自我单独下了尾的简单独代理方,这是出因之,因为自之相知节点数组([SDUser defaulUser].contactsArray)不需要各个一样潮得到都进展翻新,而且这三只代理方在实际上采用过程遭到,自动调取的次数过多,比如添加完好友或者去除完好友都能够自动调取这三只代理方,为了不必要的劳动,所以我只是用了后边的星星点点单代理方法.还是那句话,大家好依据自己的骨子里情形自行调用不同之代理方法.

咱们先看一下SDChat中于-(void)xmppRoster:(XMPPRoster *)sender didReceiveRosterItem:(DDXMLElement *)item;骚栋还开了如何的操作.首先,我们沾到各个一个密友节点item,然后我们先行判断item节点的订阅信息subscription的价值,我们要之至交是两头互订阅,也尽管是”subscription”属性也”both”、”from”、”to”才是我们需要之好友节点.所以符合这三种情况的且是咱们用之相知节点,所以if的罗标准就出了,如下代码所示.其他订阅类型不同之节点我们后会说到实际的情况.

if ([[[item attributeForName:@"subscription"] stringValue] isEqualToString:@"both"]||[[[item attributeForName:@"subscription"] stringValue] isEqualToString:@"from"]||[[[item attributeForName:@"subscription"] stringValue] isEqualToString:@"to"]) {

}

于筛好后,我们需要做的政工就是是赢得到item节点的JID信息了,这里我们只需要两行代码就足以就了.

NSString *SJid = [[item attributeForName:@"jid"] stringValue];

XMPPJID *jid = [XMPPJID jidWithString:SJid];

不管是头界面及出示好友的JID信息,还是后期显示电子名片信息,我们且亟待事先周历好友节点数组([SDUser defaulUser].contactsArray)判断数组中是否早已是拖欠好友信息了.这样做的由是因-(void)xmppRoster:(XMPPRoster *)sender didReceiveRosterItem:(DDXMLElement *)item;其一代理方也许针对一个密友节点获取多次,如果我们不进行选择性的长的话,数组可能会见起好友重复的景的,所以我们需要事先判断是否是拖欠好友信息,具体代码如下所示.(关于isDeleteFriend布尔值的在的含义,当我们抹好友的时,订阅信息subscription的值可能并无是”remove”,有或是”both”,所有我们这边要加一个布尔值,后面的勾好友,我们见面详细说明的.)

BOOL isExist = NO;

for (SDContactModel *contact in self.user.contactsArray) {

       if ([contact.jid.user isEqualToString:jid.user]) {

            isExist = YES;

          }
}         

判定了是否在好友信息之后,我们尽管得依据isExist这个布尔值来判定了是否如加加多少了,添加数据经过如下代码所示,这里自己是取得了忘年交的刺信息进行的长,前期的语可以直接上加JID.

if (!isExist) {
    //添加数据
    XMPPvCardTemp *vCard =  [[SDXmppManager defaulManager].vCardTempModule vCardTempForJID:jid shouldFetch:YES];

    SDContactModel *contact =[[SDContactModel alloc]init];
    contact.jid = jid;
    contact.vCard =vCard;
    contact.isAvailable = NO;

    [self.user.contactsArray addObject:contact];

}

面就打服务器获取到相知数据的基本流程了.

</br>

知音数据本地整理代码有

当我们得好友数据好之后,我们并无是直展现到页面上,我们要对忘年交数据开展整然后再次展现到界面的上.我们由此-(void)xmppRosterDidEndPopulating:(XMPPRoster *)sender;夫代理方来调取我们的知音数据整理方法-(void)networkingWithContactsArray;.

-(void)xmppRosterDidEndPopulating:(XMPPRoster *)sender{

    [self networkingWithContactsArray];

}

SDChat的知音界面是接近于微信的知心人界面的,是分组展示的.所以,数据存储的完整思路是,列表的数据源是储存于一个字典当中,我们管首字母相同之JID或者是用户称存储于一个数组电子科技当中.每个key是各一个JID的首字母大写(或者是用户称的首字母大写).因为字典是无序的,那么怎样就有序的排呢?我们用建立另外一个数组作为排序数组,同时也于在索引数组的作用.我们将字典中具有的Key放入数组中,然后排序,数据提取过程被我们才需要依据数组的排列顺序拿取即可.示意图如下所示.

那我们看一下实在代码过程遭到,对于字典的多少增长整理部分,首先我们而初始化字典对象,然后我们遍历好友节点数组([SDUser defaulUser].contactsArray),取出我们要排序的诸一个首要字符串(不管是JID还是用户称).我们调用-(NSString *)transform:(NSString *)chinese斯点子回去首字母并且特别写.在此主意被我们来几乎栽状态用处理,一种植是沾字符串失败,也就是说传入的凡一个nil值,我们一直回到
“#”
,另外一种是要是首字母是数字,那么我们也是用回到”#”的.所以这样回去首字母所使用到的点子总共就有矣三个,两单用来判断是否是多次组,一个虽说是截取并且开展字母大写的操作.三个点子如下所示.

//截取首字母并且大写
-(NSString *)transform:(NSString *)chinese{

    if (chinese == nil ||[chinese isEqualToString:@""]) {

        return @"#";

    }

    NSMutableString *pinyin = [chinese mutableCopy];
    CFStringTransform((__bridge CFMutableStringRef)pinyin, NULL, kCFStringTransformMandarinLatin, NO);
    CFStringTransform((__bridge CFMutableStringRef)pinyin, NULL, kCFStringTransformStripCombiningMarks, NO);

    NSString *subString = [[pinyin uppercaseString] substringWithRange:NSMakeRange(0, 1)];

    if ([self isPureInt:subString] || [self isPureFloat:subString]) {

        return  @"#";
    }

    return subString;
}

//判断是否为整型:
- (BOOL)isPureInt:(NSString*)string{
    NSScanner* scan = [NSScanner scannerWithString:string];
    int val;
    return [scan scanInt:&val] && [scan isAtEnd];
}
//判断是否为浮点型:
- (BOOL)isPureFloat:(NSString*)string{
    NSScanner* scan = [NSScanner scannerWithString:string];
    float val;
    return[scan scanFloat:&val] && [scan isAtEnd];
}

那么通过返回首字母,我们需要判定一下时之字典对象中是否曾在了改分组的反复组,如果是,那么直接存储,如果未有,那么初始化一个数组之后,以首假名为Key,空数组为Value保存至字典中,然后再次将数据存储到数组中错过.具体代码如下所示.

if (self.contactsPinyinDic[firstWord] ==nil) {

    //如果联系人字典数组中没有该分组,那么就初始化一个分组数组,然后存储.
    NSMutableArray *sectionArray =[NSMutableArray  arrayWithCapacity:16];

    [sectionArray addObject:contact];

    [self.contactsPinyinDic setValue:sectionArray forKey:firstWord];

}else{

    NSMutableArray *sectionArray =self.contactsPinyinDic[firstWord];

    [sectionArray addObject:contact];

}

长完成以后,我们虽待对索引数组进行操作了,首先我们还是先初始化我们的索引数组,初始化的经过被,我们就是管所有的key值添加至我们的数组当中去.然后我们要丰富一个空字符串@"",这是以给”新的心上人”那个分组做准备的.代码如下所示.

self.indexArray = [NSMutableArray arrayWithArray:self.contactsPinyinDic.allKeys];
[self.indexArray addObject:@""];//添加一个空的字符串,用于菜单分组

接下来,我们对索引数组进行遍历排序操作.

    for (int i = 0; i<self.indexArray.count; i++) {

        for (int j = 0; j<i; j++) {

            if (self.indexArray[j]>self.indexArray[i]) {

                NSString *objString = self.indexArray[j];
                self.indexArray[j] =  self.indexArray[i];
                self.indexArray[i] = objString;

            }
        }
    }

倘若有”#”,为了界面的丽,我们把”#”放在索引数组的终极一各,然后,我们虽刷新我们的页面就可.

//索引数组移动#号到最后.
if ([self isIncludeWithJing]) {

    [self.indexArray removeObject:@"#"];

    [self.indexArray addObject:@"#"];
}

[self.contactsList reloadData];

如此以tableView的数据源方法吃,分组个数为索引数组的元素个数self.indexArray.count;每一个section中元素的个数(除了一个分组)都是吧字典中对应的诸一个value数组的个数.

然后,我们就算可以做出开始的界面的指南来了.当然矣,这样的镜头需要我们举行过多干活之,也是我们下一样首博客所设说交之,电子名片的实现.

</br>

结束


SDChat中之知音获取的逻辑和代办方就说交此地了,这里自己要事先声明一下,SDChat中或者还设有着Bug,如果发生另外问题,欢迎联系骚栋,谢谢.接下来的相同首我认为该先行拿XMPPFramework电子名片的落实说一下,XMPPFramework我觉得最坑的饶是增长好友这同样片了,逻辑比较多,准备以第五篇中进行讲解说明.希望大家连关注~最后把SDChat的传递门送给大家.大家好对照着Demo来拘禁本篇博客.

–>SDChat传送门🚪

</br>

相关文章