PubNub 本地消息重复?
PubNub local messages duplicating?
对于我的 pubnub 聊天应用程序,我在本地存储了一些消息以防止它使用大量 wifi/data。它似乎工作正常,但有时最后一条消息会重复。这是我的保存、加载、重新加载代码。
#pragma mark - PubNub manager methods
- (NSString *)parseMessage:(id)message
{
if ([message isKindOfClass:[NSDictionary class]]) {
NSDictionary *messageAsDict = message;
if ([[messageAsDict objectForKey:@"text"] isKindOfClass:[NSString class]]) {
NSString *messageString = [messageAsDict objectForKey:@"text"];
if (messageString || messageString.length > 0) {
return messageString;
} else {
return @"Unable To Parse Message";
}
} else {
return @"Unable To Parse Message";
}
} else if ([message isKindOfClass:[NSString class]]) {
NSString *messageString = message;
if (messageString.length > 0) {
return messageString;
} else {
return @"Unable To Parse Message";
}
} else {
return @"Unable To Parse Message";
}
}
- (void)saveObjects
{
NSError *error;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *docDir = [paths objectAtIndex:0];
NSString *messagesDirectoryPath = [docDir stringByAppendingPathComponent:@"Messaging"];
if (![[NSFileManager defaultManager] fileExistsAtPath:messagesDirectoryPath]) {
[[NSFileManager defaultManager] createDirectoryAtPath:messagesDirectoryPath withIntermediateDirectories:YES attributes:nil error:&error];
}
NSString *messagesPath = [messagesDirectoryPath stringByAppendingPathComponent:messageFile];
NSString *timeTokenPath = [messagesDirectoryPath stringByAppendingPathComponent:timeTokenFile];
NSString *timeTokenString = [NSString stringWithFormat:@"%ld", (long)lastTimeToken];
[messagesArray writeToFile:messagesPath atomically:YES];
[timeTokenString writeToFile:timeTokenPath atomically:YES encoding:NSUTF8StringEncoding error:&error];
}
- (void)loadObjects
{
NSError *error;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *docDir = [paths objectAtIndex:0];
NSString *messagesDirectoryPath = [docDir stringByAppendingPathComponent:@"Messaging"];
NSString *messagesPath = [messagesDirectoryPath stringByAppendingPathComponent:messageFile];
NSString *timeTokenPath = [messagesDirectoryPath stringByAppendingPathComponent:timeTokenFile];
messagesArray = [NSMutableArray arrayWithContentsOfFile:messagesPath];
if (!messagesArray) {
messagesArray = [[NSMutableArray alloc] init];
[self saveObjects];
}
NSString *timeTokenString = [NSString stringWithContentsOfFile:timeTokenPath encoding:NSUTF8StringEncoding error:&error];
if (![timeTokenString isEqualToString:@""]) {
lastTimeToken = [timeTokenString integerValue];
} else {
lastTimeToken = [self currentTimeToken];
[self saveObjects];
}
}
- (void)reloadMessages
{
messagesArray = [[NSMutableArray alloc] init];
//Get all the chats you missed
[self.pnClient historyForChannel:kCHAT_CHANNEL withCompletion:^(PNHistoryResult *result, PNErrorStatus *status) {
// Check whether request successfully completed or not.
if (!status.isError) {
// Handle downloaded history using:
// result.data.start - oldest message time stamp in response
// result.data.end - newest message time stamp in response
// result.data.messages - list of messages
// Get messages
for (id message in result.data.messages) {
[messagesArray addObject:[self parseMessage:message]];
}
// Set timetoken
lastTimeToken = [self parsePNTimeToken:result.data.end];
// Save stuff
[self saveObjects];
dispatch_async(dispatch_get_main_queue(), ^{
[self.messagesTable reloadData];
[self scrollToBottom];
});
} else {
// Request processing failed.
UIAlertController *errorController = [UIAlertController alertControllerWithTitle:@"Error" message:@"Could not recieve messages" preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:nil];
UIAlertAction *retryAction = [UIAlertAction actionWithTitle:@"Retry" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
[status retry];
}];
[errorController addAction:cancelAction];
[errorController addAction:retryAction];
[self presentViewController:errorController animated:YES completion:nil];
}
}];
}
- (void)addMessage:(PNMessageResult *)message
{
[messagesArray addObject:[self parseMessage:message.data.message]];
lastTimeToken = [message.data.timetoken integerValue] + 1;
[self saveObjects];
}
- (NSInteger)parsePNTimeToken:(NSNumber *)timeToken
{
return trunc([timeToken integerValue] / pow(10, 7));
}
- (NSInteger)currentTimeToken
{
return [[NSDate date] timeIntervalSince1970];
}
- (void)updateLostMessages
{
[self.pnClient historyForChannel:kCHAT_CHANNEL start:[NSNumber numberWithInteger:lastTimeToken] end:[NSNumber numberWithInteger:[self currentTimeToken]] limit:NSIntegerMax withCompletion:^(PNHistoryResult *result, PNErrorStatus *status) {
NSArray *tempResultArray = result.data.messages;
for (id message in tempResultArray) {
[messagesArray addObject:[self parseMessage:message]];
NSLog(@"%@", [self parseMessage:message]);
}
lastTimeToken = [self currentTimeToken] + 1;
[self saveObjects];
[self loadObjects];
dispatch_async(dispatch_get_main_queue(), ^{
[self.messagesTable reloadData];
[self scrollToBottom];
});
}];
}
这些方法非常简单。 parseMessage:
一个从任何地方获取消息并解析要显示的文本。 saveObjects
将 timeToken 和消息保存到磁盘,并加载它们。时间标记方法只是将 PN 时间标记转换为精度较低的格式并获取当前时间标记。 updateLostMessages
获取从最后一个消息时间令牌到当前的所有消息,而不是获取所有消息。
在 viewDidLoad
我调用 [self loadObjects]
然后 [self updateLostMessages]
问题是消息重复!帮助表示赞赏。另外,抱歉代码太长了。
哈哈,傻我。我只是忘记了重新加载方法中的 + 1
。好吧,对于任何想要使用此代码在本地存储消息而不是获取所有消息的人来说,给你。此代码存储最后一条消息的时间令牌 (+1),并获取从 x 时间令牌到现在的所有消息。
对于我的 pubnub 聊天应用程序,我在本地存储了一些消息以防止它使用大量 wifi/data。它似乎工作正常,但有时最后一条消息会重复。这是我的保存、加载、重新加载代码。
#pragma mark - PubNub manager methods
- (NSString *)parseMessage:(id)message
{
if ([message isKindOfClass:[NSDictionary class]]) {
NSDictionary *messageAsDict = message;
if ([[messageAsDict objectForKey:@"text"] isKindOfClass:[NSString class]]) {
NSString *messageString = [messageAsDict objectForKey:@"text"];
if (messageString || messageString.length > 0) {
return messageString;
} else {
return @"Unable To Parse Message";
}
} else {
return @"Unable To Parse Message";
}
} else if ([message isKindOfClass:[NSString class]]) {
NSString *messageString = message;
if (messageString.length > 0) {
return messageString;
} else {
return @"Unable To Parse Message";
}
} else {
return @"Unable To Parse Message";
}
}
- (void)saveObjects
{
NSError *error;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *docDir = [paths objectAtIndex:0];
NSString *messagesDirectoryPath = [docDir stringByAppendingPathComponent:@"Messaging"];
if (![[NSFileManager defaultManager] fileExistsAtPath:messagesDirectoryPath]) {
[[NSFileManager defaultManager] createDirectoryAtPath:messagesDirectoryPath withIntermediateDirectories:YES attributes:nil error:&error];
}
NSString *messagesPath = [messagesDirectoryPath stringByAppendingPathComponent:messageFile];
NSString *timeTokenPath = [messagesDirectoryPath stringByAppendingPathComponent:timeTokenFile];
NSString *timeTokenString = [NSString stringWithFormat:@"%ld", (long)lastTimeToken];
[messagesArray writeToFile:messagesPath atomically:YES];
[timeTokenString writeToFile:timeTokenPath atomically:YES encoding:NSUTF8StringEncoding error:&error];
}
- (void)loadObjects
{
NSError *error;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *docDir = [paths objectAtIndex:0];
NSString *messagesDirectoryPath = [docDir stringByAppendingPathComponent:@"Messaging"];
NSString *messagesPath = [messagesDirectoryPath stringByAppendingPathComponent:messageFile];
NSString *timeTokenPath = [messagesDirectoryPath stringByAppendingPathComponent:timeTokenFile];
messagesArray = [NSMutableArray arrayWithContentsOfFile:messagesPath];
if (!messagesArray) {
messagesArray = [[NSMutableArray alloc] init];
[self saveObjects];
}
NSString *timeTokenString = [NSString stringWithContentsOfFile:timeTokenPath encoding:NSUTF8StringEncoding error:&error];
if (![timeTokenString isEqualToString:@""]) {
lastTimeToken = [timeTokenString integerValue];
} else {
lastTimeToken = [self currentTimeToken];
[self saveObjects];
}
}
- (void)reloadMessages
{
messagesArray = [[NSMutableArray alloc] init];
//Get all the chats you missed
[self.pnClient historyForChannel:kCHAT_CHANNEL withCompletion:^(PNHistoryResult *result, PNErrorStatus *status) {
// Check whether request successfully completed or not.
if (!status.isError) {
// Handle downloaded history using:
// result.data.start - oldest message time stamp in response
// result.data.end - newest message time stamp in response
// result.data.messages - list of messages
// Get messages
for (id message in result.data.messages) {
[messagesArray addObject:[self parseMessage:message]];
}
// Set timetoken
lastTimeToken = [self parsePNTimeToken:result.data.end];
// Save stuff
[self saveObjects];
dispatch_async(dispatch_get_main_queue(), ^{
[self.messagesTable reloadData];
[self scrollToBottom];
});
} else {
// Request processing failed.
UIAlertController *errorController = [UIAlertController alertControllerWithTitle:@"Error" message:@"Could not recieve messages" preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:nil];
UIAlertAction *retryAction = [UIAlertAction actionWithTitle:@"Retry" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
[status retry];
}];
[errorController addAction:cancelAction];
[errorController addAction:retryAction];
[self presentViewController:errorController animated:YES completion:nil];
}
}];
}
- (void)addMessage:(PNMessageResult *)message
{
[messagesArray addObject:[self parseMessage:message.data.message]];
lastTimeToken = [message.data.timetoken integerValue] + 1;
[self saveObjects];
}
- (NSInteger)parsePNTimeToken:(NSNumber *)timeToken
{
return trunc([timeToken integerValue] / pow(10, 7));
}
- (NSInteger)currentTimeToken
{
return [[NSDate date] timeIntervalSince1970];
}
- (void)updateLostMessages
{
[self.pnClient historyForChannel:kCHAT_CHANNEL start:[NSNumber numberWithInteger:lastTimeToken] end:[NSNumber numberWithInteger:[self currentTimeToken]] limit:NSIntegerMax withCompletion:^(PNHistoryResult *result, PNErrorStatus *status) {
NSArray *tempResultArray = result.data.messages;
for (id message in tempResultArray) {
[messagesArray addObject:[self parseMessage:message]];
NSLog(@"%@", [self parseMessage:message]);
}
lastTimeToken = [self currentTimeToken] + 1;
[self saveObjects];
[self loadObjects];
dispatch_async(dispatch_get_main_queue(), ^{
[self.messagesTable reloadData];
[self scrollToBottom];
});
}];
}
这些方法非常简单。 parseMessage:
一个从任何地方获取消息并解析要显示的文本。 saveObjects
将 timeToken 和消息保存到磁盘,并加载它们。时间标记方法只是将 PN 时间标记转换为精度较低的格式并获取当前时间标记。 updateLostMessages
获取从最后一个消息时间令牌到当前的所有消息,而不是获取所有消息。
在 viewDidLoad
我调用 [self loadObjects]
然后 [self updateLostMessages]
问题是消息重复!帮助表示赞赏。另外,抱歉代码太长了。
哈哈,傻我。我只是忘记了重新加载方法中的 + 1
。好吧,对于任何想要使用此代码在本地存储消息而不是获取所有消息的人来说,给你。此代码存储最后一条消息的时间令牌 (+1),并获取从 x 时间令牌到现在的所有消息。