From 30375a0362abd78c8aa2c86de4e37d41b4d07c1b Mon Sep 17 00:00:00 2001 From: Andreas Linde Date: Thu, 19 Feb 2015 15:05:03 +0100 Subject: [PATCH] Fix a crash in feedback list view with attachments The crash was happening when an attachment was still loading in the last cell but before loading ended, the number of cells changed by deleting a message. Once the attachment was loaded, the crash occured. This is no fixed by using a safer approach on updating the cell content for loaded attachments by using notifications and letting the cells decide themselves if they need to re-display their content. --- Classes/BITFeedbackListViewCell.m | 44 +++++++++++++++++++++++++ Classes/BITFeedbackListViewController.m | 2 +- Classes/BITFeedbackManager.m | 2 ++ Classes/BITFeedbackManagerPrivate.h | 2 ++ 4 files changed, 49 insertions(+), 1 deletion(-) diff --git a/Classes/BITFeedbackListViewCell.m b/Classes/BITFeedbackListViewCell.m index d55e27897f..b0c999ad49 100644 --- a/Classes/BITFeedbackListViewCell.m +++ b/Classes/BITFeedbackListViewCell.m @@ -26,11 +26,13 @@ * OTHER DEALINGS IN THE SOFTWARE. */ +#import "HockeySDK.h" #import "HockeySDKPrivate.h" #import "BITFeedbackListViewCell.h" #import "BITFeedbackMessageAttachment.h" #import "BITActivityIndicatorButton.h" +#import "BITFeedbackManagerPrivate.h" #define BACKGROUNDCOLOR_DEFAULT BIT_RGBCOLOR(245, 245, 245) #define BACKGROUNDCOLOR_ALTERNATE BIT_RGBCOLOR(235, 235, 235) @@ -70,6 +72,8 @@ @property (nonatomic, strong) UIView *accessoryBackgroundView; +@property (nonatomic, strong) id updateAttachmentNotification; + @end @@ -107,13 +111,53 @@ _labelText.dataDetectorTypes = UIDataDetectorTypeAll; _attachmentViews = [NSMutableArray new]; + [self registerObservers]; } return self; } +- (void)dealloc { + [self unregisterObservers]; +} + #pragma mark - Private +- (void) registerObservers { + __weak typeof(self) weakSelf = self; + if (nil == _updateAttachmentNotification) { + _updateAttachmentNotification = [[NSNotificationCenter defaultCenter] addObserverForName:kBITFeedbackUpdateAttachmentThumbnail + object:nil + queue:NSOperationQueue.mainQueue + usingBlock:^(NSNotification *note) { + typeof(self) strongSelf = weakSelf; + [strongSelf updateAttachmentFromNotification:note]; + }]; + } +} + +- (void) unregisterObservers { + if (_updateAttachmentNotification) { + [[NSNotificationCenter defaultCenter] removeObserver:_updateAttachmentNotification]; + _updateAttachmentNotification = nil; + } +} + +- (void) updateAttachmentFromNotification:(NSNotification *)note { + if (!self.message) return; + if (!self.message.attachments) return; + if (self.message.attachments.count == 0) return; + if (!note.object) return; + if (![note.object isKindOfClass:[BITFeedbackMessageAttachment class]]) return; + + BITFeedbackMessageAttachment *attachment = (BITFeedbackMessageAttachment *)note.object; + if (![self.message.attachments containsObject:attachment]) return; + + // The attachment is part of the message used for this cell, so lets update it. + [self setAttachments:self.message.previewableAttachments]; + [self setNeedsLayout]; +} + - (UIColor *)backgroundColor { if (self.backgroundStyle == BITFeedbackListViewCellBackgroundStyleNormal) { diff --git a/Classes/BITFeedbackListViewController.m b/Classes/BITFeedbackListViewController.m index 48a3cacea4..17d96addfb 100644 --- a/Classes/BITFeedbackListViewController.m +++ b/Classes/BITFeedbackListViewController.m @@ -652,7 +652,7 @@ if (responseData.length) { dispatch_async(dispatch_get_main_queue(), ^{ [attachment replaceData:responseData]; - [self.tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationNone]; + [[NSNotificationCenter defaultCenter] postNotificationName:kBITFeedbackUpdateAttachmentThumbnail object:attachment]; [[BITHockeyManager sharedHockeyManager].feedbackManager saveMessages]; }); } diff --git a/Classes/BITFeedbackManager.m b/Classes/BITFeedbackManager.m index 86222ed13e..c457c510b3 100644 --- a/Classes/BITFeedbackManager.m +++ b/Classes/BITFeedbackManager.m @@ -53,6 +53,8 @@ #define kBITFeedbackLastMessageID @"HockeyFeedbackLastMessageID" #define kBITFeedbackAppID @"HockeyFeedbackAppID" +NSString *const kBITFeedbackUpdateAttachmentThumbnail = @"BITFeedbackUpdateAttachmentThumbnail"; + @interface BITFeedbackManager() @property (nonatomic, strong) UITapGestureRecognizer *tapRecognizer; diff --git a/Classes/BITFeedbackManagerPrivate.h b/Classes/BITFeedbackManagerPrivate.h index 23ae1d988a..54c5ded86d 100644 --- a/Classes/BITFeedbackManagerPrivate.h +++ b/Classes/BITFeedbackManagerPrivate.h @@ -30,6 +30,8 @@ #if HOCKEYSDK_FEATURE_FEEDBACK +extern NSString *const kBITFeedbackUpdateAttachmentThumbnail; + #import "BITFeedbackMessage.h" @interface BITFeedbackManager () {