在MQTTKit中使用相同的客户端ID初始化新客户端时,无法接收脱机消息

时间:2014-10-03 20:31:01

标签: ios objective-c mqtt

目前,当具有相同客户端ID的MQTTClient对象重新初始化然后连接到代理时,似乎不会保留会话。

请考虑以下代码:

//Just a tiny wrapper around MQTTClient for custom methods
@property (nonatomic, strong) RAMQTTClient *client;

@implementation MQTTViewController

- (void)viewDidLoad
{
    [super viewDidLoad];

    //The selector gets called whenever a new message is received
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didReceiveMessage:) name:@"didReceiveMessage" object:nil];

    //Initialises an MQTT client with QOS=1 and cleanSession=NO
    _client = [[RAMQTTClient alloc]initWithId:@"client-1"];
}

-(void)didReceiveMessage:(NSNotification *)notification {
    NSString *data = (NSString *)notification.object;
    NSLog(@"Received: %@", data);
}

// Use a switch action to subscribe and disconnect
- (IBAction)switchUpdated:(id)sender {
    BOOL on = [sender isOn];
    if (on) {
        [_client listenToTopic:@"a~1"];
    } else {
        [_client disconnect];
    }
}

@end

只要_client对象未被销毁,断开连接和重新连接就会检索在该时间间隔内发送的脱机消息。但是,如果客户端重新初始化然后开始监听,我就不会收到任何离线消息。

以下是RAMQTTClient的实施:

typedef void (^ConnectionCompletionHandler)(MQTTConnectionReturnCode code);

@interface RAMQTTClient()
@property (strong, nonatomic) MQTTClient *client;
@property (nonatomic) MQTTConnectionReturnCode connectionCode;
@end

@implementation RAMQTTClient

-(instancetype)initWithId:(NSString*)id {
    if (self = [super init]) {
        _client = [[MQTTClient alloc]initWithClientId:id cleanSession:NO];
    }
    return self;
}

-(BOOL)isRunning {
    return _client.connected;
}

-(NSString *)id {
    return _client.clientID;
}

-(void)connectWithCompletionHandler:(ConnectionCompletionHandler)handler {
    if (!_client.connected) {
        [_client connectToHost:@"localhost" completionHandler:handler];
    }
}

-(void)listenToTopic:(NSString *)topic {
    ConnectionCompletionHandler completionHandler = ^(MQTTConnectionReturnCode code) {
        NSLog(@"RAMQTTClient: %@ connected", _client.clientID);
        _connectionCode = code;
        if (code == ConnectionAccepted) {
            [_client subscribe:topic withQos:AtLeastOnce completionHandler:^(NSArray *grantedQos) {
                NSLog(@"RAMQTTClient: Listening to %@", topic);
                [_client setMessageHandler:^(MQTTMessage *message) {
                    NSLog(@"Message => %@",message.payloadString);
                    [[NSNotificationCenter defaultCenter]postNotificationName:@"didReceiveMessage"
                                                                       object:message.payloadString];
                }];
            }];
        }
    };
    [self connectWithCompletionHandler:completionHandler];
}

-(void)disconnect {
    if (_client.connected) {
        [_client disconnectWithCompletionHandler:^(NSUInteger code) {
            NSLog(@"RAMQTTClient: %@ Disconnected with code %u", _client.clientID, code);
        }];
    }
}

@end

你们之前有没有遇到过这类问题?有解决方法吗?

1 个答案:

答案 0 :(得分:1)

对于那些感兴趣的人,我已经明白了。问题是在订阅主题后设置了消息处理程序。由于离线消息在您订阅时立即到达,因此客户端在接收消息处理程序之前无法等待或设置消息处理程序。结果,即使消息到达,它们也不会被发送到处理程序。在订阅频道之前设置消息处理程序解决了这个问题。

[_client setMessageHandler:^(MQTTMessage *message) {
    NSLog(@"Message => %@",message.payloadString);
    [[NSNotificationCenter defaultCenter]postNotificationName:@"didReceiveMessage"
                                                       object:message.payloadString];
}];
[_client subscribe:topic withQos:AtLeastOnce completionHandler:^(NSArray *grantedQos) {
            NSLog(@"RAMQTTClient: Listening to %@", topic);
}];