iOS上的XMPPFramework -xmppRoomDidDestroy:没有被调用

Posted

技术标签:

【中文标题】iOS上的XMPPFramework -xmppRoomDidDestroy:没有被调用【英文标题】:XMPPFramework on iOS -xmppRoomDidDestroy: not getting called 【发布时间】:2013-09-16 19:40:54 【问题描述】:

我正在使用适用于 ios/OSX 的 XMPP 框架开发 iPhone 应用程序,并且我正在使用 XEP-0045 扩展(多用户聊天)。我已经成功创建和配置了房间,我可以邀请其他用户并与他们聊天。当我去破坏我创建的房间时,问题就出现了。我已经遵循了在框架内执行的代码路径,并且我已经弄清楚了为什么框架没有触发该方法,但是我不确定鉴于我看到的行为它会如何触发该方法.

该行为如下:

1) 我通过调用 [room destroyRoom] 请求销毁房间

2) 然后我看到 XMPPRoom 类设置了它的 XMPPIDResponse 跟踪器来监视服务器将发回的“结果”iq 节,说它已成功删除房间。

3)(这就是问题所在)我从房间收到一个出席信息节,说它现在不可用(因为我也是房间的住户)然后框架清除响应跟踪器并调用 -xmppRoomDidLeave :.

4) 服务器然后发回“结果” iq 节,说房间已成功删除,但没有人再听了。这会导致错过对 xmppRoomDidDestroy 的调用。

此行为与我在 XEP-0045 定义中阅读的内容一致,鉴于此,我不确定如何调用 -xmppRoomDidDestroy: 委托。我在这里做错了吗?

【问题讨论】:

嗨,扎卡里,我遇到了完全相同的问题。你找到解决办法了吗? -xmppRoomDidDestroy 在销毁时组中有更多成员时调用,但在我的环境中,问题是我应该只销毁我是其中最后一个成员的房间... 嘿莱特曼。我知道这已经晚了,但希望它会有所帮助。不幸的是,我无法找到解决方案。我最终不得不使用自己的 XMPPIDResponseTracker 来监视它并自己调用代理。 【参考方案1】:

我遇到了同样的问题,这是我的解决方案:

在 XMPPRoom 方法中

- (void)xmppStream:(XMPPStream *)sender didReceivePresence:(XMPPPresence *)presence

替换

[responseTracker removeAllIDs];

与:

if ([x elementForName:@"destroy"]) 
    NSArray *allKeys = [responseTracker allIDs];
    for (NSString *key in allKeys) 
        SEL aSel = [responseTracker selectorForElementID:key];
        if (aSel != @selector(handleDestroyRoomResponse:withInfo:)) 
            [responseTracker removeID:key];
        
    
 else 
    [responseTracker removeAllIDs];

在 XMPPIDTracker.h 中添加新公共方法的声明

- (NSArray *)allIDs;

- (SEL)selectorForElementID:(NSString *)elementID;

也在XMPPBasicTrackingInfo接口中添加

@property (nonatomic, readonly) SEL selector;

在 XMPPIDTracker.m 中添加两个公共方法

- (NSArray *)allIDs 
    return [dict allKeys];


- (SEL)selectorForElementID:(NSString *)elementID 
    id <XMPPTrackingInfo> info = [dict objectForKey:elementID];
    if ([info isKindOfClass:[XMPPBasicTrackingInfo class]]) 
        return [(XMPPBasicTrackingInfo *)info selector];
    
    return nil;

在@implementation XMPPBasicTrackingInfo 的末尾添加

@synthesize selector;

基本上,这段代码会删除所有响应跟踪器,除了 handleDestroyRoomResponse:withInfo: 因为我们需要这个处理程序来响应 IQ destroy 节。

我希望这会有所帮助。

【讨论】:

您好,我已按照您提供的步骤进行操作,但无法正常工作。请指导我。【参考方案2】:

与最新的XMPPFramework 3.6.6 相同的问题。

解决办法如下:

仍然使用destroyRoom 函数,xmppStream:didReceivePresence:xmppRoomDidLeave: 将被调用,通过在两个委托中添加NSLog 进行测试,然后我使用 Spark(Windows 版本)破坏房间,Xcode 控制台打印以下内容文字:

<presence xmlns="jabber:client" type="unavailable" from="wei@conference.10.50.200.94/admin" to="admin@10.50.200.94/iOS">
    <x xmlns="http://jabber.org/protocol/muc#user">
        <item affiliation="none" role="none"></item>
        <destroy>
            <reason>destroy room</reason>
        </destroy>
    </x>
</presence>

我使用&lt;destroy&gt; 元素来确定destroyRoom 操作。

- (void)xmppStream:(XMPPStream *)sender didReceivePresence:(XMPPPresence *)presence

    /*
     <presence xmlns="jabber:client" type="unavailable" from="wei@conference.10.50.200.94/admin" to="admin@10.50.200.94/iOS"><x xmlns="http://jabber.org/protocol/muc#user"><item affiliation="none" role="none"></item><destroy><reason>destroy room</reason></destroy></x></presence>
     */
    // NSLog(@"%s %@", __FUNCTION__, presence);
    if ([presence.fromStr containsString:@"conference"]) 
        NSXMLElement *x = [presence elementForName:@"x"];
        if (x) 
            NSXMLElement *destroy = [x elementForName:@"destroy"];
            if (destroy) 
                XMPPJID *roomJID = presence.from.bareJID;
                // TODO: do something with the roomJID
            
        
    

但是XMPPFramework 发送一个空的&lt;destory/&gt; 元素,我猜openfire 服务器只是忽略&lt;destroy/&gt; 和响应&lt;presence&gt;..&lt;/presence&gt; 而没有&lt;destroy&gt;

修改XMPPFramework中的destroyRoom函数或实现以下委托添加销毁原因。

- (XMPPIQ *)xmppStream:(XMPPStream *)sender willSendIQ:(XMPPIQ *)iq

    /*
     <iq type="set" to="weixin@conference.10.50.200.94" id="BCF55C6A-9C5E-4740-BE6A-63E17B5C58F6"><query xmlns="http://jabber.org/protocol/muc#owner"><destroy></destroy></query></iq>
     */
    if ([iq isSetIQ]) 
        NSXMLElement *query = [iq elementForName:@"query" xmlns:XMPPMUCOwnerNamespace];
        if (query) 
            NSXMLElement *destroy = [query elementForName:@"destroy"];
            if (destroy) 
                NSXMLElement *reason = [destroy elementForName:@"reason"];
                if (!reason) 
                    reason = [NSXMLElement elementWithName:@"reason" stringValue:@"destroy reason"];
                    [destroy addChild:reason];
                
            
        
    
    return iq;

【讨论】:

以上是关于iOS上的XMPPFramework -xmppRoomDidDestroy:没有被调用的主要内容,如果未能解决你的问题,请参考以下文章

XMPPFramework:尝试更新 VCard 上的昵称

ios 通过 xmppframework 传输文件

iOS开发--XMPPFramework--好友列表

如何在目标c中通过ios中的XMPPFramework连接XMPP服务器

iOS XMPPFramework registerWithPassword 错误

如何在iOS的XMPPFramework中实现发送好友请求的方式?