我的自定义类上的xmppstream代理方法没有被调用

7

最近我开始接触xmppframework,但是遇到了一个问题。我能够连接到本地网络上的服务器,但是xmppstreamdelegate方法在我的自定义类中无法被调用,但在appdelegate类上完全正常工作。有人可以帮帮我吗?委托只支持appdelegate类吗?

头文件:

@interface XmppClass : NSObject<XMPPStreamDelegate>{
    XMPPStream *xmppStream;
    Login * loginDetail;
    BOOL allowSelfSignedCertificates;
    BOOL allowSSLHostNameMismatch;
}
@property (nonatomic, strong, readonly) XMPPStream *xmppStream;

@property (nonatomic, strong) Login *loginDetail;
- (id)initWithLogin:(Login *) loginrefernce;
- (BOOL)connect;
- (void)disconnect;
- (void)setupStream;
@end

实现:

@implementation XmppClass

@synthesize xmppStream;
@synthesize loginDetail;
- (id)initWithLogin:(Login *) loginrefernce
{
    self = [super init];
    if (self) {
        self.loginDetail=loginrefernce;
        [DDLog addLogger:[DDTTYLogger sharedInstance]];
        [self setupStream];
        [self connect];
    }
    return self;
}
- (void)setupStream
{
NSAssert(xmppStream == nil, @"Method setupStream invoked multiple times");
// Setup xmpp stream
// 
// The XMPPStream is the base class for all activity.
// Everything else plugs into the xmppStream, such as modules/extensions and delegates.

xmppStream = [[XMPPStream alloc] init];
#if !TARGET_IPHONE_SIMULATOR
{
// Want xmpp to run in the background?
// 
// P.S. - The simulator doesn't support backgrounding yet.
//        When you try to set the associated property on the simulator, it simply fails.
//        And when you background an app on the simulator,
//        it just queues network traffic til the app is foregrounded again.
//        We are patiently waiting for a fix from Apple.
//        If you do enableBackgroundingOnSocket on the simulator,
//        you will simply see an error message from the xmpp stack when it fails to set the property.
xmppStream.enableBackgroundingOnSocket = YES;
}
#endif

NSLog(@"setup stream");
[xmppStream addDelegate:self delegateQueue:dispatch_get_main_queue()];

[xmppStream setHostName:@"10.68.202.123"];
//[xmppStream setHostPort:8070];

allowSelfSignedCertificates = NO;
allowSSLHostNameMismatch = NO;

// You may need to alter these settings depending on the server you're connecting to

}

- (BOOL)connect
{
    NSLog(@"connect");
    if (![xmppStream isDisconnected]) {
        return YES;
    }


//
// If you don't want to use the Settings view to set the JID, 
// uncomment the section below to hard code a JID and password.
// 
// myJID = @"user@gmail.com/xmppframework";
// myPassword = @"";
if (self.loginDetail.emailId == nil || self.loginDetail.password == nil) {
    return NO;
}

[xmppStream setMyJID:[XMPPJID jidWithString:[self.loginDetail.emailId      stringByAppendingString:@"/pc"]]];


NSError *error = nil;
if (![xmppStream connect:&error])
{

    NSLog(@"Error connecting: %@", error);

    return NO;
}

return YES;
}

- (void)disconnect
{
    [xmppStream disconnect];
}
- (void)xmppStream:(XMPPStream *)sender socketDidConnect:(GCDAsyncSocket *)socket 
{
    DDLogVerbose(@"%@: %@", THIS_FILE, THIS_METHOD);
}

- (void)xmppStream:(XMPPStream *)sender willSecureWithSettings:(NSMutableDictionary *)settings
{
    DDLogVerbose(@"%@: %@", THIS_FILE, THIS_METHOD);
    NSLog(@"some security thing");
    if (allowSelfSignedCertificates)
    {
        [settings setObject:[NSNumber numberWithBool:YES] forKey:(NSString  *)kCFStreamSSLAllowsAnyRoot];
    }
    if (allowSSLHostNameMismatch)
    {
        [settings setObject:[NSNull null] forKey:(NSString *)kCFStreamSSLPeerName];
    }
    else
   {
        // Google does things incorrectly (does not conform to RFC).
        // Because so many people ask questions about this (assume xmpp framework is broken),
        // I've explicitly added code that shows how other xmpp clients "do the right thing"
        // when connecting to a google server (gmail, or google apps for domains).
        NSString *expectedCertName = nil;
        NSString *serverDomain = xmppStream.hostName;
        NSString *virtualDomain = [xmppStream.myJID domain];
        if ([serverDomain isEqualToString:@"talk.google.com"])
        {
             if ([virtualDomain isEqualToString:@"gmail.com"])
             {
                  expectedCertName = virtualDomain;
             }
             else
             {
                  expectedCertName = serverDomain;
             }
        }
        else if (serverDomain == nil)
        {
             expectedCertName = virtualDomain;
        }
        else
        {
             expectedCertName = serverDomain;
        }
        if (expectedCertName)
        {
             [settings setObject:expectedCertName forKey:(NSString *)kCFStreamSSLPeerName];
        }
}

}

- (void)xmppStreamDidSecure:(XMPPStream *)sender
{
    DDLogVerbose(@"%@: %@", THIS_FILE, THIS_METHOD);
}

- (void)xmppStreamDidConnect:(XMPPStream *)sender
{
    DDLogVerbose(@"%@: %@", THIS_FILE, THIS_METHOD);
    NSLog(@"connected");
    NSError *error = nil;
    if (![[self xmppStream] authenticateWithPassword:self.loginDetail.password error:&error])
    {
            DDLogError(@"Error authenticating: %@", error);
    }
}

- (void)xmppStreamDidAuthenticate:(XMPPStream *)sender
{
    DDLogVerbose(@"%@: %@", THIS_FILE, THIS_METHOD);
    NSLog(@"authenticated");

}

- (void)xmppStream:(XMPPStream *)sender didNotAuthenticate:(NSXMLElement *)error
{
    DDLogVerbose(@"%@: %@", THIS_FILE, THIS_METHOD);
    NSLog(@"did not authenticate");
}

- (BOOL)xmppStream:(XMPPStream *)sender didReceiveIQ:(XMPPIQ *)iq
{
    DDLogVerbose(@"%@: %@", THIS_FILE, THIS_METHOD);
    return NO;
}

- (void)xmppStream:(XMPPStream *)sender didReceiveMessage:(XMPPMessage *)message
{
    DDLogVerbose(@"%@: %@", THIS_FILE, THIS_METHOD);

    // A simple example of inbound message handling.

}

- (void)xmppStream:(XMPPStream *)sender didReceivePresence:(XMPPPresence *)presence
{
    DDLogVerbose(@"%@: %@ - %@", THIS_FILE, THIS_METHOD, [presence fromStr]);
}

- (void)xmppStream:(XMPPStream *)sender didReceiveError:(id)error
{
    DDLogVerbose(@"%@: %@", THIS_FILE, THIS_METHOD);
}

- (void)xmppStreamDidDisconnect:(XMPPStream *)sender withError:(NSError *)error
{
    DDLogVerbose(@"%@: %@", THIS_FILE, THIS_METHOD);
    NSLog(@"%@",error);
}
@end

请您把代码缩进一下好吗? - paulmelnikow
你的 XmppClass 实例是否调用了 -setupStream 方法?还有 -connect 方法吗?[xmppStream connect] 是否返回 YES?你正在使用 ARC 吗?输出是什么?创建 XmppClass 实例的代码是什么? - paulmelnikow
1
您可以将任何类用作您的XMPPStreamDelegate。 - paulmelnikow
@noa -setupStream和-connect是从-(id)initWithLogin:(Login *)loginrefernce中调用的,而intuen是在xmpp类的实例上调用的:XmppClass * xmppRef = [[XmppClass alloc] initWithLogin:self]; - Suhas_United
我还有一个问题困扰着我,与xmppframework相关,它似乎是一个解析器问题。在运行XMPPFramework的示例项目时,我遇到了这个问题。如果您能帮助我解决这个问题,我将不胜感激:[链接]http://stackoverflow.com/questions/15355228/connection-disconnects-with-error-internal-error-code-1-errordomain-libxmlerro - Suhas_United
显示剩余3条评论
3个回答

1
很可能的问题是您的类实例,作为XMPPStream的代理,在调用代理方法之前被释放了。通过将此类作为其他类的属性或实例变量或使用dispatch_once使其更加持久化。例如,更改:
YourClass *instance = [[YourClass alloc] init];
instance.xmppStream = .... 

by

@property(nonatomic, strong) YourClass *instance;
self.instance = [[YourClass alloc] init];
self.instance.xmppStream = .... 

在这里,YourClass包含XMPPStream并且是其委托人。

我已经撰写了一篇关于这个问题的大型博客文章。这是一个相当普遍的情况。 http://blog.alwawee.com/2013/07/31/on-xmppframework-delegate-method-not-being-called/


我遇到了同样的问题。你的博客文章不见了,我能在其他地方找到它吗?谢谢! - ChrisC
1
这是一篇关于XMPPFramework委托方法未被调用的博客文章。 - Denis Kutlubaev

0
我曾经遇到过同样的问题...这个方法对我有用。希望它也能对你有用,只需在你的代码中进行以下更改即可。
Static XmppClass *selfRef = nil;
@implementation XmppClass
@synthesize xmppStream;
- (void)setupStream
{
// Setup xmpp stream
selfRef = [[XmppClass alloc] init];
xmppStream = [[XMPPStream alloc] init];
[xmppStream addDelegate:selfRef delegateQueue:dispatch_get_main_queue()];

0

你可以使用组播,类似这样的方式

[[self appDelegate].xmppStream addDelegate:self delegateQueue:dispatch_get_main_queue()];

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接