【问题标题】:XMPPRoster will not post new buddy to XMPP serverXMPPRoster 不会将新好友发布到 XMPP 服务器
【发布时间】:2013-01-16 19:49:46
【问题描述】:

我正在尝试使用这行代码将新伙伴添加到用户名册中:

XMPPJID jid = [XMPPJID jidWithString:[NSString stringWithFormat:@"%@@localhost",
                                      addBuddyTextField.text]];
[appDelegate.xmppRoster addUser:jid withNickname:addBuddyTextField.text];

这行得通。其他用户收到订阅请求通知,他可以接受,一切正常。新好友将被添加到 XMPPRosterMemoryStorage 并显示在 [XMPPRosterMemoryStorage unsortedUsers] NSArray 中,以便可以在 UI 上显示当前名单及其所有好友。

但是一旦用户注销并重新启动应用程序,整个名册就消失了,他添加了所有好友。 [XMPPRoster fetchRoster] 和下面的方法 [XMPPRosterMemoryStorage unsortedUsers] 返回一个没有项目的 NSArray。

我必须将好友更新(添加、删除)发布到 XMPPServer 吗?还是我的 XMPPserver (ejabberd) 不支持名册?

这是我用来激活 XMPPRoster 的代码:

xmppRosterMemStorage = [[XMPPRosterMemoryStorage alloc] init];
xmppRoster = [[XMPPRoster alloc] initWithRosterStorage:xmppRosterMemStorage
                                         dispatchQueue:dispatch_get_main_queue()];
[xmppRoster addDelegate:self delegateQueue:dispatch_get_main_queue()];
xmppRoster.autoAcceptKnownPresenceSubscriptionRequests = false;
xmppRoster.autoFetchRoster = true;
[xmppRoster activate:xmppStream];
[xmppRoster fetchRoster];

【问题讨论】:

  • 你会发布你的代码吗?您是否尝试过使用另一个客户端操作名册,然后检查您是否可以成功地从服务器获取名册? ejabberd 有一个名册模块;您确认它已启用吗?
  • mod_roster 在我的 ejabberd.cfg 中启用。这就是我激活 XMPProster 的方式:pastebin.com/hmRRXuth。 Adium 似乎正确添加了联系人,并且能够在注销/登录后检索它们。即使我使用 Adium 添加好友,然后使用我的应用使用同一帐户登录,xmpproster 也是空的。
  • 好吧,XMPPRoster 的代表被解雇了,但名册是空的。如果好友可用或正在订阅等,则属于 XMPPStream 的 didReceivePresence 委托方法确实会返回,但这并不能满足真正的花名册。
  • 如果您在代码中添加好友,它会显示在 Adium 中吗?
  • 在我的应用中添加的好友也会显示在 Adium 的好友列表中(同一帐户)。因此,问题应该在于在我的应用程序中检索花名册。需要说明的是:我正在获取名册并等待代表消息xmppRosterDidChangexmppRosterDidPopulate 被解雇。但是只有当我的名单中的用户改变了他的存在时,他们才会被解雇。获取花名册(等待一段时间)并使用 unsortedUsers 检查花名册中的任何用户返回一个空数组。

标签: ios xmpp xmppframework


【解决方案1】:

从上面的讨论中,听起来您的服务器正在处理您的名册请求。使用您的设置代码,我无法重现您遇到的问题。

您可以尝试打开日志记录,看看阅读协议日志是否有助于您了解正在发生的事情:

#import "DDTTYLogger.h"

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
    [DDLog addLogger:[DDTTYLogger sharedInstance]];

    ...

或者在你的服务器上尝试我的测试代码,如果问题消失,从那里开始工作:

#import "AppDelegate.h"
#import "XMPPFramework.h"
#import "DDTTYLogger.h"
#import "DDLog.h"

static const int ddLogLevel = LOG_LEVEL_VERBOSE;

NSString * const XMPPAuthenticationMethodPlain = @"Plain";
NSString * const XMPPAuthenticationMethodDigestMD5 = @"Digest-MD5";

NSString * const OptionHostName = @"...";
NSUInteger const OptionPort = 5222;
BOOL const OptionOldSchoolSSL = NO;
NSString * const OptionJID = @"...";
NSString * const OptionAuthenticationMethod = @"Digest-MD5";
NSString * const OptionPassword = @"...";

@interface AppDelegate () <XMPPStreamDelegate, XMPPRosterMemoryStorageDelegate>

@property (retain) XMPPStream *xmppStream;
@property (retain) XMPPRosterMemoryStorage *xmppRosterMemStorage;
@property (retain) XMPPRoster *xmppRoster;

@end

@implementation AppDelegate

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
    [DDLog addLogger:[DDTTYLogger sharedInstance]];

    self.xmppStream = [[XMPPStream alloc] init];
    [self.xmppStream addDelegate:self delegateQueue:dispatch_get_main_queue()];
    self.xmppStream.hostName = OptionHostName;
    self.xmppStream.hostPort = OptionPort;
    self.xmppStream.myJID = [XMPPJID jidWithString:OptionJID];

    self.xmppRosterMemStorage = [[XMPPRosterMemoryStorage alloc] init];
    self.xmppRoster = [[XMPPRoster alloc] initWithRosterStorage:self.xmppRosterMemStorage
                                             dispatchQueue:dispatch_get_main_queue()];
    [self.xmppRoster addDelegate:self delegateQueue:dispatch_get_main_queue()];
    [self.xmppRoster activate:self.xmppStream];

    NSError *error = nil;
    if (OptionOldSchoolSSL)
        [self.xmppStream oldSchoolSecureConnect:&error];
    else
        [self.xmppStream connect:&error];
}

-(void)applicationWillTerminate:(NSNotification *)notification {
    [self.xmppStream removeDelegate:self];
    [self.xmppStream disconnect];
}

-(void)xmppStreamDidConnect:(XMPPStream *)sender {
    Class authClass = nil;
    if ([OptionAuthenticationMethod isEqual:XMPPAuthenticationMethodPlain])
        authClass = [XMPPPlainAuthentication class];
    else if ([OptionAuthenticationMethod isEqual:XMPPAuthenticationMethodDigestMD5])
        authClass = [XMPPDigestMD5Authentication class];
    else {
        DDLogWarn(@"Unrecognized auhthentication method '%@', falling back on Plain",
                  OptionAuthenticationMethod);
        authClass = [XMPPPlainAuthentication class];
    }
    id<XMPPSASLAuthentication> auth = [[authClass alloc] initWithStream:sender
                                                               password:OptionPassword];
    NSError *error = nil;
    if (![sender authenticate:auth error:&error])
        NSLog(@"Error authenticating: %@", error);
}

-(void)xmppRosterDidPopulate:(XMPPRosterMemoryStorage *)sender {
    NSLog(@"users: %@", [sender unsortedUsers]);
    // My subscribed users do print out
}

@end

如果我将名册设置代码移动到-xmppStreamDidAuthenticate,它也可以工作,但是在这种情况下我确实需要手动调用-fetchRoster

【讨论】:

  • 现在好像可以了!是的,即使客户端未连接到服务器,我也能获取花名册是个好主意。你太棒了,诺亚!
  • 你好,当我使用 ip 作为主机名时,它没有进行身份验证.....但是当我使用服务器名时,它没有连接到主机。它说检查主机名。请帮忙
  • @Ronak,请发布一个新问题。
  • @noa 我无法创建新问题。你能来聊天吗
猜你喜欢
  • 2012-08-19
  • 2019-09-10
  • 2014-01-16
  • 1970-01-01
  • 2015-07-28
  • 2019-07-16
  • 1970-01-01
  • 1970-01-01
  • 2019-05-23
相关资源
最近更新 更多