iOS XMPP房间的创建注意事项及误区

想必大家都是用这个方法来分配一个Room对象:

_m_xmppRoom = [[XMPPRoom alloc] initWithRoomStorage:_xmppRoomDatajid:RoomJID dispatchQueue:queue2 ];

那我这里就详细介绍一下各个参数该如何设置.


第一个参数,是XMPPRoomCoreDataStorage类型,他是为这个房间分配一个coredata的数据库,但由于我是用自己的数据库,所以就用

_xmppRoomData = [[XMPPRoomCoreDataStoragealloc] initWithInMemoryStore];

来实例化之。



第二个参数则是Room的JID这个需要自己分配,不能跟服务器已经有的JID重复。



第三个参数则是房间所在队列,此参数特别重要,请大家一定注意。xmpp的提供了一个IOS 的demo,此demo很大程度上误导了大家,因为他初始化queue都用的是

dispatch_get_main_queue()

这是主线程队列(没错就是管UI更新的那个),他可能是为了图写domo方便所以才用这个队列。但是实际的聊天软件,你敢在写主线程队列里面?一个也许还行,20个房间呢?程序根本就卡到爆。所以我建议大家重新新建一个串行队列

e.g :

queue2 =dispatch_queue_create("com.我的工程.RoomQueue",NULL); // 串行queue

你也许想问,为什么一定要用串行?并行为什么不行?因为,stream也是串行的,也是一条一条往服务器送。



注意事项:最好自己抽象一个RoomClass,一个聊天室就是一个RoomClass对象,这样可以方便管控房间消息加入离开房间等。下面贴上我自己的RoomClass和初始化RoomClass方法:

RoomClass.h

//

//  RoomClass.h

//  MICI13

//

//  Created by   on 14-6-17.

//  Copyright (c) 2014 DoubleKill. All rights reserved.

//


#import <Foundation/Foundation.h>

#import "XMPPFramework.h"

#import "XMPPRoom.h"

#import "CoreDataManager.h"

//#import "CentreControl.h"

#import "TFTimer.h"

@interface RoomClass :NSObject<XMPPRoomDelegate>{

    

   NSTimer *RoomTimer;

   XMPPStream  *stream;


    

    

}

//#define kNofSingleMessage               @"kNofSingleMessage"

//#define kNofRoomMessage                 @"kNofRoomMessage"

//#define kNofRoomDidJion                 @"kNofRoomDidJion"

//#define kNofRoomReceiveInvitation       @"kNofRoomReceiveInvitation"

typedefvoid(^handler)(BOOL result,id obj) ;

@property (nonatomic,copy)handler RoomBlock;//

@property (nonatomic,strong) XMPPRoomCoreDataStorage *xmppRoomData;

@property (nonatomic,strong) XMPPRoom *m_xmppRoom;

@property (nonatomic,copy) NSString *Jid;

@property (nonatomic,assign) BOOL    isCame;

@property (nonatomic,assign) BOOL    isLoadHistory;

- (id)initWithJid:(NSString *)jid members:(NSMutableArray *)members stream:(XMPPStream*)xmppstream Finish:(handler)finished;

-(void)leaveRoom;

@end


RoomClass.m

//

//  RoomClass.m

//  MICI13

//

//  Created by   on 14-6-17.

//  Copyright (c) 2014 DoubleKill. All rights reserved.

//


#import "RoomClass.h"


@implementation RoomClass{

   XMPPStream * m_stream;

   NSMutableArray * members;

   NSString *Roomjid;

   NSDate *dateIn;

}

extern dispatch_queue_t queue2;

//

//NSString *const kXMPPmyJID = @"kXMPPmyJID";

//NSString *const kXMPPmyPassword = @"kXMPPmyPassword";

- (id)initWithJid:(NSString *)RoomJID members:(NSMutableArray *)member stream:(XMPPStream*)xmppstream Finish:(handler)finished

{

   _RoomBlock = finished;

   m_stream = xmppstream;

   Roomjid = RoomJID;

   members = member;

    

   self = [superinit];

   if (self) {

        // Custom initialization


        _xmppRoomData = [[XMPPRoomCoreDataStoragealloc] initWithInMemoryStore];

        _m_xmppRoom = [[XMPPRoomalloc] initWithRoomStorage:_xmppRoomDatajid:[XMPPJIDjidWithString:RoomJID] dispatchQueue:queue2members:member];

        [_m_xmppRoomactivate:xmppstream];

        

        

       if ([_m_xmppRoom

             preJoinWithNickname:[[NSUserDefaultsstandardUserDefaults] objectForKey:@"kXMPPmyJID"]])

        {

            //            NSLog(@"room created RoomJid:%@",RoomJID);

           NSXMLElement *xml = [[NSXMLElementalloc] initWithXMLString:@"<history maxstanzas='0'/>"error:nil];

            //            NSLog(@"room xml == {%@}",xml.XMLString);

            [_m_xmppRoomjoinRoomUsingNickname:[[NSUserDefaultsstandardUserDefaults] objectForKey:@"kXMPPmyJID"]history:xml];

        }

        [_m_xmppRoomaddDelegate:selfdelegateQueue:queue2];

       NSLog(@"init roomJID%@",RoomJID);


    }

    return self;

}

-(void)leaveRoom{

   if (!_isCame) {

        [RoomTimerpauseTimer];

    }

    

    [_m_xmppRoom leaveRoom];

    [_m_xmppRoom deactivate];

//

    

    [_m_xmppRoomremoveDelegate:selfdelegateQueue:queue2];

    

}

- (void)xmppRoomDidCreate:(XMPPRoom *)sender{

//    NSLog(@"xmppRoomDidCreate~");

}

- (void)xmppRoom:(XMPPRoom *)sender didFetchConfigurationForm:(NSXMLElement *)configForm{

//    NSLog(@"%s~~~",__FUNCTION__);

}


- (void)xmppRoom:(XMPPRoom *)sender willSendConfiguration:(XMPPIQ *)roomConfigForm{

//    NSLog(@"%s~~~",__FUNCTION__);

}


- (void)xmppRoom:(XMPPRoom *)sender didConfigure:(XMPPIQ *)iqResult{

//    NSLog(@"%s~~~",__FUNCTION__);

}

- (void)xmppRoom:(XMPPRoom *)sender didNotConfigure:(XMPPIQ *)iqResult{

//    NSLog(@"%s~~~",__FUNCTION__);

}


- (void)xmppRoomDidJoin:(XMPPRoom *)sender{

    NSLog(@"xmppRoomDidJoin~");

   _isCame = YES;

    _isLoadHistory =NO;

   Group *group = [GroupGroupAtJid:Roomjid];

    

   if (!(group.since.length >5) ) {

       dateIn = [NSDatedate];

    }

    [RoomTimerpauseTimer];

   _RoomBlock(YES,sender);

    [[NSNotificationCenterdefaultCenter] postNotificationName:@"kNofRoomDidJion"object:nil];

    XMPPJID *jid = [XMPPJIDjidWithString:[[NSUserDefaultsstandardUserDefaults] stringForKey:@"kXMPPmyJID"]];

    NSString *Sjid =[[NSUserDefaultsstandardUserDefaults] stringForKey:@"kXMPPmyJID"];

    //設置管理員

   NSLog(@"edit==%@",[sendereditRoomPrivileges:[NSArrayarrayWithObjects:[XMPPRoomitemWithRole:@"moderator"jid:jid], nil]]);

    //配置房間參數

    NSXMLElement *roomConfigure = [[NSXMLElementalloc] initWithXMLString:[NSStringstringWithFormat:@"<x xmlns=\"jabber:x:data\" type=\"form\"><title>房间配置</title><instructions>已创建房间“xx”。要接受缺省配置,请单击确定按钮。或填写以下表单以完成设置:</instructions><field var=\"FORM_TYPE\" type=\"hidden\"><value>http://jabber.org/protocol/muc#roomconfig</value></field><field var=\"muc#roomconfig_roomname\" type=\"text-single\" label=\"房间名称\"><value>xx</value></field><field var=\"muc#roomconfig_roomdesc\" type=\"text-single\" label=\"描述\"><value>xx</value></field><field var=\"muc#roomconfig_changesubject\" type=\"boolean\" label=\"允许占有者更改主题\"><value>0</value></field><field var=\"muc#roomconfig_maxusers\" type=\"list-single\" label=\"最大房间占有者人数\"><option label=\"10\"><value>10</value></option><option label=\"20\"><value>20</value></option><option label=\"30\"><value>30</value></option><option label=\"40\"><value>40</value></option><option label=\"50\"><value>50</value></option><option label=\"\"><value>0</value></option><value>30</value></field><field var=\"muc#roomconfig_presencebroadcast\" type=\"list-multi\" label=\" Presence Broadcast 的角色\"><option label=\"主持者\"><value>moderator</value></option><option label=\"参与者\"><value>participant</value></option><option label=\"访客\"><value>visitor</value></option><value>moderator</value><value>participant</value><value>visitor</value></field><field var=\"muc#roomconfig_publicroom\" type=\"boolean\" label=\"列出目录中的房间\"><value>1</value></field><field var=\"muc#roomconfig_persistentroom\" type=\"boolean\" label=\"房间是持久的\"><value>1</value></field><field var=\"muc#roomconfig_moderatedroom\" type=\"boolean\" label=\"房间是适度的\"><value>0</value></field><field var=\"muc#roomconfig_membersonly\" type=\"boolean\" label=\"房间仅对成员开放\"><value>0</value></field><field type=\"fixed\"><value>注意:缺省情况下,只有管理员才可以在仅用于邀请的房间中发送邀请。</value></field><field var=\"muc#roomconfig_allowinvites\" type=\"boolean\" label=\"允许占有者邀请其他人\"><value>1</value></field><field var=\"muc#roomconfig_passwordprotectedroom\" type=\"boolean\" label=\"需要密码才能进入房间\"><value>0</value></field><field type=\"fixed\"><value>如果需要密码才能进入房间,则您必须在下面指定密码。</value></field><field var=\"muc#roomconfig_roomsecret\" type=\"text-private\" label=\"密码\" /><field var=\"muc#roomconfig_whois\" type=\"list-single\" label=\"能够发现占有者真实 JID的角色\"><option label=\"主持者\"><value>moderators</value></option><option label=\"任何人\"><value>anyone</value></option><value>anyone</value></field><field var=\"muc#roomconfig_enablelogging\" type=\"boolean\" label=\"登录房间对话\"><value>0</value></field><field var=\"x-muc#roomconfig_reservednick\" type=\"boolean\" label=\"仅允许注册的昵称登录\"><value>0</value></field><field var=\"x-muc#roomconfig_canchangenick\" type=\"boolean\" label=\"允许使用者修改昵称\"><value>1</value></field><field type=\"fixed\"><value>允许用户注册房间</value></field><field var=\"x-muc#roomconfig_registration\" type=\"boolean\" label=\"允许用户注册房间\"><value>1</value></field><field type=\"fixed\"><value>您可以指定该房间的管理员。请在每行提供一个 JID</value></field><field var=\"muc#roomconfig_roomadmins\" type=\"jid-multi\" label=\"房间管理员\" /><field type=\"fixed\"><value>您可以指定该房间的其他拥有者。指定该房间的管理员。请在每行提供一个 JID</value></field><field var=\"muc#roomconfig_roomadmins\" type=\"jid-multi\" label=\"房间管理员\" /><field type=\"fixed\"><value>您可以指定该房间的其他拥有者。\350\257请在每行提供一个 JID</value></field><field var=\"muc#roomconfig_roomowners\" type=\"jid-multi\" label=\"房间拥有者\"><value>%@</value></field></x>",Sjid] error:Nil];

    [senderconfigureRoomUsingOptions:roomConfigure];

    [sender fetchConfigurationForm];

    [senderfetchBanList];

    [sender fetchMembersList];

    [sender fetchModeratorsList];

}

- (void)xmppRoomDidLeave:(XMPPRoom *)sender{

    [_m_xmppRoom leaveRoom];

    [_m_xmppRoom deactivate];

    _xmppRoomData  =nil;

    [_m_xmppRoomremoveDelegate:selfdelegateQueue:queue2];


}


- (void)xmppRoomDidDestroy:(XMPPRoom *)sender{

//    NSLog(@"%s~~~",__FUNCTION__);

}


- (void)xmppRoom:(XMPPRoom *)sender occupantDidJoin:(XMPPJID *)occupantJID withPresence:(XMPPPresence *)presence{

//    NSLog(@"%s~~~",__FUNCTION__);

}

- (void)xmppRoom:(XMPPRoom *)sender occupantDidLeave:(XMPPJID *)occupantJID withPresence:(XMPPPresence *)presence{

//    NSLog(@"%s~~~",__FUNCTION__);

}

- (void)xmppRoom:(XMPPRoom *)sender occupantDidUpdate:(XMPPJID *)occupantJID withPresence:(XMPPPresence *)presence{

//    NSLog(@"%s~~~",__FUNCTION__);

}


/**

 * Invoked when a message is received.

 * The occupant parameter may be nil if the message came directly from the room, or from a non-occupant.

 **/

- (void)xmppRoom:(XMPPRoom *)sender didReceiveMessage:(XMPPMessage *)message fromOccupant:(XMPPJID *)occupantJID{

//    NSLog(@"didReceiveMessage:%@",message);

    NSError *error;//排除不符合格式的消息,免得奔溃

   NSXMLElement *xml = [[NSXMLElementalloc] initWithXMLString:[NSStringstringWithFormat:@"<a>%@</a>",[messagebody]] error:&error];

    if ([[xmlchildAtIndex:0]stringValue].length>2) {

       return;

    }

    

   if ([Group isExist:sender.roomJID.bare]) {

        

    }else{

       return;

    }

   NSDate *dateNow = [NSDatedate];

   float interval = [dateNow timeIntervalSinceDate:dateIn];

   BOOL isRead = NO;

   Group *group = [GroupGroupAtJid:Roomjid];

   if (!(group.since.length >5)) {

//        NSLog(@"groupId:%@",group.jid);

       if (interval > 10) {//是新消息

//            NSLog(@"是新消息");

            isRead =NO;

            [GroupupdateSince:RoomjidSince:@"111111"];

        }else {//不是新消息

//            NSLog(@"不是新消息");

            isRead =YES;

           dateIn = [NSDatedate];

        }

    }

    

    if (![message.from.resourceisEqualToString:[[NSUserDefaultsstandardUserDefaults] objectForKey:@"kXMPPmyJID"]]) {

        //        NSLog(@"message.body:%@ jid:%@",message.body,sender.roomJID.bare);

        

       switch ([[[xml childAtIndex:0]stringValue] intValue]) {

           case 0://文本

            {

                if ([message.from.resourceisEqualToString:[[NSUserDefaultsstandardUserDefaults] objectForKey:@"kXMPPmyJID"]]) {//判断是否自己曾经发出去的

                    [MessageInsertMessage:[[xml childAtIndex:1]stringValue] Jid:sender.roomJID.barefrom:message.from.resourceisSendByMe:NOdate:[[xml childAtIndex:2]stringValue] type:MessageTypeMeisRead:isRead bigPic:nil];

                }else{

                    [MessageInsertMessage:[[xml childAtIndex:1]stringValue] Jid:sender.roomJID.barefrom:message.from.resourceisSendByMe:NOdate:[[xml childAtIndex:2]stringValue] type:MessageTypeOtherisRead:isRead bigPic:nil];

                }

                

            }

               break;

                

           case 1://音频

            {

                if ([message.from.resourceisEqualToString:[[NSUserDefaultsstandardUserDefaults] objectForKey:@"kXMPPmyJID"]]) {

                    [MessageInsertMessage:[[xml childAtIndex:1]stringValue] Jid:[messagefrom].bare from:message.from.resourceisSendByMe:NOdate:[[xml childAtIndex:2]stringValue] type:AudioTypeMeisRead:isRead bigPic:nil];

                }else{

                    [MessageInsertMessage:[[xml childAtIndex:1]stringValue] Jid:[messagefrom].bare from:message.from.resourceisSendByMe:NOdate:[[xml childAtIndex:2]stringValue] type:AudioTypeOtherisRead:isRead bigPic:nil];

                }

                

            }

               break;

           case 2://文件

            {

                

            }

               break;

           case 3://图片

            {

               NSString *bigPic;

               if (xml.childCount>3) {

                    bigPic = [[xmlchildAtIndex:3]stringValue];

                }else{

                    bigPic =nil;

                }


                if ([message.from.resourceisEqualToString:[[NSUserDefaultsstandardUserDefaults] objectForKey:@"kXMPPmyJID"]]) {

                    

                    [MessageInsertMessage:[[xml childAtIndex:1]stringValue] Jid:[messagefrom].bare from:message.from.resourceisSendByMe:NOdate:[[xml childAtIndex:2]stringValue] type:ImageTypeMeisRead:isRead bigPic:bigPic];

                }else {

                    [MessageInsertMessage:[[xml childAtIndex:1]stringValue] Jid:[messagefrom].bare from:message.from.resourceisSendByMe:NOdate:[[xml childAtIndex:2]stringValue] type:ImageTypeOtherisRead:isRead bigPic:bigPic];

                }

                

            }

               break;

                

           default:

               break;

        }

        

        [[NSNotificationCenterdefaultCenter] postNotificationName:@"kNofSingleMessage"object:[NSDictionarydictionaryWithObject:message forKey:@"message"]];

    }

}


- (void)xmppRoom:(XMPPRoom *)sender didFetchBanList:(NSArray *)items{

    NSLog(@"%s~~~",__FUNCTION__);

}

- (void)xmppRoom:(XMPPRoom *)sender didNotFetchBanList:(XMPPIQ *)iqError{

    NSLog(@"%s~~~",__FUNCTION__);

}


- (void)xmppRoom:(XMPPRoom *)sender didFetchMembersList:(NSArray *)items{

    NSLog(@"%s~~~",__FUNCTION__);

}

- (void)xmppRoom:(XMPPRoom *)sender didNotFetchMembersList:(XMPPIQ *)iqError{

    NSLog(@"%s~~~",__FUNCTION__);

}


- (void)xmppRoom:(XMPPRoom *)sender didFetchModeratorsList:(NSArray *)items{

//    NSLog(@"%s~~~",__FUNCTION__);

}

- (void)xmppRoom:(XMPPRoom *)sender didNotFetchModeratorsList:(XMPPIQ *)iqError{

//    NSLog(@"%s~~~%@",__FUNCTION__,sender.roomJID.bare);

}


- (void)xmppRoom:(XMPPRoom *)sender didEditPrivileges:(XMPPIQ *)iqResult{

//    NSLog(@"%s~~~",__FUNCTION__);

}

- (void)xmppRoom:(XMPPRoom *)sender didNotEditPrivileges:(XMPPIQ *)iqError{

//    NSLog(@"%s~~~",__FUNCTION__);

}


@end


初始化房间方法:

-(void)creatAllRoom{

    for (RoomClass *roomin RoomArray) {

        [roomleaveRoom];

    }

    [m_roomClassremoveAllObjects];

    [RoomArrayremoveAllObjects];

   for (Group * groupin [Group queryFromGroup:nil]) {

       if ([group.hasJionedboolValue]) {

            /**< 异步并回调主线程,常用ui更新*/

            dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT ,0), ^{

               NSLog(@"yes creatAllRoom");

                [[CentreControlsharedController] creatRoom:group.jid Nickname:[[NSUserDefaults standardUserDefaults] objectForKey:@"kXMPPmyJID"]members:NULL];

               sleep(0.020);

               dispatch_async(queue, ^{

//                    NSLog(@"to do with ui");

                });

            });

           

        }

    }

}

-(void)creatRoom:(NSString *)RoomJID Nickname:(NSString *)userNickName members:(NSMutableArray *)member Finish:(handler)finished{

   RoomClass *room = [[RoomClassalloc] initWithJid:RoomJID members:memberstream:xmppStreamFinish:finished];


   if (m_roomClass==nil) {

        m_roomClass = [[NSMutableDictionaryalloc] init];

    }

   if (RoomArray ==nil || [RoomArraycount]==0) {

       RoomArray = [[NSMutableArrayalloc] init];

    }

   if ([m_roomClassobjectForKey:RoomJID]!=nil ) {

        

    }else{

        [m_roomClasssetObject:room forKey:RoomJID];

        [RoomArrayaddObject:room];

   }

}


你可能感兴趣的:(iOS XMPP房间的创建注意事项及误区)