From a4124dbda49ace0ef81cbe9a4eaecea2d5112eeb Mon Sep 17 00:00:00 2001 From: Andreas Linde Date: Sun, 29 Sep 2013 17:14:31 +0200 Subject: [PATCH] Fix removing observers correctly Thanks to @idpaterson for reporting this in https://github.com/bitstadium/HockeySDK-iOS/pull/64 --- Classes/BITFeedbackManager.m | 64 ++++++++++++++++++++++++--------- Classes/BITStoreUpdateManager.m | 49 +++++++++++++++++-------- Classes/BITUpdateManager.m | 64 +++++++++++++++++++++++++-------- 3 files changed, 132 insertions(+), 45 deletions(-) diff --git a/Classes/BITFeedbackManager.m b/Classes/BITFeedbackManager.m index 765a4760bf..c1219b9f7a 100644 --- a/Classes/BITFeedbackManager.m +++ b/Classes/BITFeedbackManager.m @@ -58,8 +58,11 @@ NSString *_feedbackDir; NSString *_settingsFile; + id _appDidBecomeActiveObserver; + id _appDidEnterBackgroundObserver; + id _networkDidBecomeReachableObserver; + BOOL _incomingMessagesAlertShowing; - BOOL _didSetupDidBecomeActiveNotifications; BOOL _didEnterBackgroundState; BOOL _networkRequestInProgress; } @@ -78,7 +81,6 @@ _showFirstRequiredPresentationModal = YES; _disableFeedbackManager = NO; - _didSetupDidBecomeActiveNotifications = NO; _networkRequestInProgress = NO; _incomingMessagesAlertShowing = NO; _lastCheck = nil; @@ -110,9 +112,7 @@ } - (void)dealloc { - [[NSNotificationCenter defaultCenter] removeObserver:self name:BITHockeyNetworkDidBecomeReachableNotification object:nil]; - - [[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationDidBecomeActiveNotification object:nil]; + [self unregisterObservers]; } @@ -138,19 +138,51 @@ } } -- (void)setupDidBecomeActiveNotifications { - if (!_didSetupDidBecomeActiveNotifications) { - NSNotificationCenter *dnc = [NSNotificationCenter defaultCenter]; - [dnc addObserver:self selector:@selector(didEnterBackgroundActions) name:UIApplicationDidEnterBackgroundNotification object:nil]; - [dnc addObserver:self selector:@selector(didBecomeActiveActions) name:UIApplicationDidBecomeActiveNotification object:nil]; - [dnc addObserver:self selector:@selector(didBecomeActiveActions) name:BITHockeyNetworkDidBecomeReachableNotification object:nil]; - _didSetupDidBecomeActiveNotifications = YES; +#pragma mark - Observers +- (void) registerObservers { + __weak typeof(self) weakSelf = self; + if(nil == _appDidEnterBackgroundObserver) { + _appDidEnterBackgroundObserver = [[NSNotificationCenter defaultCenter] addObserverForName:UIApplicationDidEnterBackgroundNotification + object:nil + queue:NSOperationQueue.mainQueue + usingBlock:^(NSNotification *note) { + typeof(self) strongSelf = weakSelf; + [strongSelf didEnterBackgroundActions]; + }]; + } + if(nil == _appDidBecomeActiveObserver) { + _appDidBecomeActiveObserver = [[NSNotificationCenter defaultCenter] addObserverForName:UIApplicationDidBecomeActiveNotification + object:nil + queue:NSOperationQueue.mainQueue + usingBlock:^(NSNotification *note) { + typeof(self) strongSelf = weakSelf; + [strongSelf didBecomeActiveActions]; + }]; + } + if(nil == _networkDidBecomeReachableObserver) { + _networkDidBecomeReachableObserver = [[NSNotificationCenter defaultCenter] addObserverForName:BITHockeyNetworkDidBecomeReachableNotification + object:nil + queue:NSOperationQueue.mainQueue + usingBlock:^(NSNotification *note) { + typeof(self) strongSelf = weakSelf; + [strongSelf didBecomeActiveActions]; + }]; } } -- (void)cleanupDidBecomeActiveNotifications { - [[NSNotificationCenter defaultCenter] removeObserver:self name:BITHockeyNetworkDidBecomeReachableNotification object:nil]; - [[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationDidBecomeActiveNotification object:nil]; +- (void) unregisterObservers { + if(_appDidEnterBackgroundObserver) { + [[NSNotificationCenter defaultCenter] removeObserver:_appDidEnterBackgroundObserver]; + _appDidEnterBackgroundObserver = nil; + } + if(_appDidBecomeActiveObserver) { + [[NSNotificationCenter defaultCenter] removeObserver:_appDidBecomeActiveObserver]; + _appDidBecomeActiveObserver = nil; + } + if(_networkDidBecomeReachableObserver) { + [[NSNotificationCenter defaultCenter] removeObserver:_networkDidBecomeReachableObserver]; + _networkDidBecomeReachableObserver = nil; + } } #pragma mark - Private methods @@ -206,7 +238,7 @@ - (void)startManager { if ([self isFeedbackManagerDisabled]) return; - [self setupDidBecomeActiveNotifications]; + [self registerObservers]; // we are already delayed, so the notification already came in and this won't invoked twice switch ([[UIApplication sharedApplication] applicationState]) { diff --git a/Classes/BITStoreUpdateManager.m b/Classes/BITStoreUpdateManager.m index 911d7318f2..2d14ccbc65 100644 --- a/Classes/BITStoreUpdateManager.m +++ b/Classes/BITStoreUpdateManager.m @@ -47,7 +47,8 @@ BOOL _updateAlertShowing; BOOL _lastCheckFailed; - BOOL _didSetupDidBecomeActiveNotifications; + id _appDidBecomeActiveObserver; + id _networkDidBecomeReachableObserver; } @@ -67,18 +68,39 @@ } } -- (void)setupDidBecomeActiveNotifications { - if (!_didSetupDidBecomeActiveNotifications) { - NSNotificationCenter *dnc = [NSNotificationCenter defaultCenter]; - [dnc addObserver:self selector:@selector(didBecomeActiveActions) name:UIApplicationDidBecomeActiveNotification object:nil]; - [dnc addObserver:self selector:@selector(didBecomeActiveActions) name:BITHockeyNetworkDidBecomeReachableNotification object:nil]; - _didSetupDidBecomeActiveNotifications = YES; +#pragma mark - Observers + +- (void) registerObservers { + __weak typeof(self) weakSelf = self; + if(nil == _appDidBecomeActiveObserver) { + _appDidBecomeActiveObserver = [[NSNotificationCenter defaultCenter] addObserverForName:UIApplicationDidBecomeActiveNotification + object:nil + queue:NSOperationQueue.mainQueue + usingBlock:^(NSNotification *note) { + typeof(self) strongSelf = weakSelf; + [strongSelf didBecomeActiveActions]; + }]; + } + if(nil == _networkDidBecomeReachableObserver) { + _networkDidBecomeReachableObserver = [[NSNotificationCenter defaultCenter] addObserverForName:BITHockeyNetworkDidBecomeReachableNotification + object:nil + queue:NSOperationQueue.mainQueue + usingBlock:^(NSNotification *note) { + typeof(self) strongSelf = weakSelf; + [strongSelf didBecomeActiveActions]; + }]; } } -- (void)cleanupDidBecomeActiveNotifications { - [[NSNotificationCenter defaultCenter] removeObserver:self name:BITHockeyNetworkDidBecomeReachableNotification object:nil]; - [[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationDidBecomeActiveNotification object:nil]; +- (void) unregisterObservers { + if(_appDidBecomeActiveObserver) { + [[NSNotificationCenter defaultCenter] removeObserver:_appDidBecomeActiveObserver]; + _appDidBecomeActiveObserver = nil; + } + if(_networkDidBecomeReachableObserver) { + [[NSNotificationCenter defaultCenter] removeObserver:_networkDidBecomeReachableObserver]; + _networkDidBecomeReachableObserver = nil; + } } @@ -90,7 +112,6 @@ _updateAvailable = NO; _lastCheckFailed = NO; _enableStoreUpdateManager = NO; - _didSetupDidBecomeActiveNotifications = NO; _updateAlertShowing = NO; _updateUIEnabled = YES; _newStoreVersion = nil; @@ -114,9 +135,7 @@ } - (void)dealloc { - [[NSNotificationCenter defaultCenter] removeObserver:self name:BITHockeyNetworkDidBecomeReachableNotification object:nil]; - - [[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationDidBecomeActiveNotification object:nil]; + [self unregisterObservers]; } @@ -374,7 +393,7 @@ self.lastCheck = [NSDate distantPast]; } - [self setupDidBecomeActiveNotifications]; + [self registerObservers]; // we are already delayed, so the notification already came in and this won't invoked twice switch ([[UIApplication sharedApplication] applicationState]) { diff --git a/Classes/BITUpdateManager.m b/Classes/BITUpdateManager.m index 96d8e117c2..8d5309ec4e 100644 --- a/Classes/BITUpdateManager.m +++ b/Classes/BITUpdateManager.m @@ -59,6 +59,10 @@ typedef NS_ENUM(NSInteger, BITUpdateAlertViewTag) { BOOL _lastCheckFailed; BOOL _sendUsageData; + id _appDidBecomeActiveObserver; + id _appDidEnterBackgroundObserver; + id _networkDidBecomeReachableObserver; + BOOL _didSetupDidBecomeActiveNotifications; BOOL _didEnterBackgroundState; @@ -111,21 +115,55 @@ typedef NS_ENUM(NSInteger, BITUpdateAlertViewTag) { } } -- (void)setupDidBecomeActiveNotifications { +#pragma mark - Observers +- (void) registerObservers { + __weak typeof(self) weakSelf = self; + if(nil == _appDidEnterBackgroundObserver) { + _appDidEnterBackgroundObserver = [[NSNotificationCenter defaultCenter] addObserverForName:UIApplicationDidEnterBackgroundNotification + object:nil + queue:NSOperationQueue.mainQueue + usingBlock:^(NSNotification *note) { + typeof(self) strongSelf = weakSelf; + [strongSelf didEnterBackgroundActions]; + }]; + } + if(nil == _appDidBecomeActiveObserver) { + _appDidBecomeActiveObserver = [[NSNotificationCenter defaultCenter] addObserverForName:UIApplicationDidBecomeActiveNotification + object:nil + queue:NSOperationQueue.mainQueue + usingBlock:^(NSNotification *note) { + typeof(self) strongSelf = weakSelf; + [strongSelf didBecomeActiveActions]; + }]; + } + if(nil == _networkDidBecomeReachableObserver) { + _networkDidBecomeReachableObserver = [[NSNotificationCenter defaultCenter] addObserverForName:BITHockeyNetworkDidBecomeReachableNotification + object:nil + queue:NSOperationQueue.mainQueue + usingBlock:^(NSNotification *note) { + typeof(self) strongSelf = weakSelf; + [strongSelf didBecomeActiveActions]; + }]; + } if (!_didSetupDidBecomeActiveNotifications) { - NSNotificationCenter *dnc = [NSNotificationCenter defaultCenter]; - [dnc addObserver:self selector:@selector(didEnterBackgroundActions) name:UIApplicationDidEnterBackgroundNotification object:nil]; - [dnc addObserver:self selector:@selector(didBecomeActiveActions) name:UIApplicationDidBecomeActiveNotification object:nil]; - [dnc addObserver:self selector:@selector(didBecomeActiveActions) name:BITHockeyNetworkDidBecomeReachableNotification object:nil]; _installationIdentification = [self stringValueFromKeychainForKey:kBITUpdateInstallationIdentification]; _didSetupDidBecomeActiveNotifications = YES; } } -- (void)cleanupDidBecomeActiveNotifications { - [[NSNotificationCenter defaultCenter] removeObserver:self name:BITHockeyNetworkDidBecomeReachableNotification object:nil]; - [[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationDidBecomeActiveNotification object:nil]; - [[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationDidEnterBackgroundNotification object:nil]; +- (void) unregisterObservers { + if(_appDidEnterBackgroundObserver) { + [[NSNotificationCenter defaultCenter] removeObserver:_appDidEnterBackgroundObserver]; + _appDidEnterBackgroundObserver = nil; + } + if(_appDidBecomeActiveObserver) { + [[NSNotificationCenter defaultCenter] removeObserver:_appDidBecomeActiveObserver]; + _appDidBecomeActiveObserver = nil; + } + if(_networkDidBecomeReachableObserver) { + [[NSNotificationCenter defaultCenter] removeObserver:_networkDidBecomeReachableObserver]; + _networkDidBecomeReachableObserver = nil; + } } @@ -161,7 +199,7 @@ typedef NS_ENUM(NSInteger, BITUpdateAlertViewTag) { } // the UI is now blocked, make sure we don't add our UI on top of it over and over again - [self cleanupDidBecomeActiveNotifications]; + [self unregisterObservers]; } } @@ -391,10 +429,8 @@ typedef NS_ENUM(NSInteger, BITUpdateAlertViewTag) { } - (void)dealloc { - [[NSNotificationCenter defaultCenter] removeObserver:self name:BITHockeyNetworkDidBecomeReachableNotification object:nil]; - + [self unregisterObservers]; [[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationWillTerminateNotification object:nil]; - [[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationDidBecomeActiveNotification object:nil]; [[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationWillResignActiveNotification object:nil]; [_urlConnection cancel]; @@ -681,7 +717,7 @@ typedef NS_ENUM(NSInteger, BITUpdateAlertViewTag) { [self performSelector:@selector(checkForUpdate) withObject:nil afterDelay:1.0f]; } } - [self setupDidBecomeActiveNotifications]; + [self registerObservers]; }