问题
I have the following code within AppDelegate. The purpose being to create a couple of observers, and then call some code. Once that code completes it then posts a notification, and the observer should then remove both observers and call the completion handler.
My issue is that it appears that the observers are not being removed as I expected. The notification is posted, and the NSLog entry is written to console, so I know that the observer is working. However, on the second time of calling, the NSLog is called twice, third time three times etc.
My thoughts are that this is to do with the removal being within the block of code that is running from the observer, however, I am unsure how I can resolve this (if indeed this is what the issue is).
Could someone be so kind as to explain how I can achieve this?
Thanks.
-(void) application:(UIApplication *)application performFetchWithCompletionHandler:
(void (^)(UIBackgroundFetchResult))completionHandler {
[[NSNotificationCenter defaultCenter] addObserverForName:@"fetchDidCompleteNewData" object:nil
queue:nil usingBlock:^(NSNotification *completed) {
//Remove Observers
[[NSNotificationCenter defaultCenter] removeObserver:self
name:@"fetchDidCompleteNewData"
object:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self
name:@"fetchDidCompleteNoData"
object:nil];
// Post completion
completionHandler(UIBackgroundFetchResultNewData);
NSLog(@"Background fetch completed... New Data");
}];
[[NSNotificationCenter defaultCenter] addObserverForName:@"fetchDidCompleteNoData" object:nil
queue:nil usingBlock:^(NSNotification *completed) {
//Remove Observers
[[NSNotificationCenter defaultCenter] removeObserver:self
name:@"fetchDidCompleteNoData"
object:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self
name:@"fetchDidCompleteNewData"
object:nil];
//post completion
completionHandler(UIBackgroundFetchResultNoData);
NSLog(@"Background fetch completed... No New Data");
}];
GetDetails *getDetails = [[GetDetails alloc] init];
[getDetails backgroundRefresh];
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
[[UIApplication sharedApplication] setMinimumBackgroundFetchInterval:UIApplicationBackgroundFetchIntervalMinimum];
return YES;
}
回答1:
You are not registering self
as an object. Moreover, when the block is pushed onto the stack by addObserverForName:
the method has not yet returned so the notification
is nil
.
Make a global object using block
, eg
__block __weak id notification;
then,
notification = [[NSNotificationCenter defaultCenter] addObserverForName:@"fetchDidCompleteNewData" object:nil queue:nil usingBlock:^(NSNotification *completed) {
//Remove Observers
[[NSNotificationCenter defaultCenter] removeObserver:notification];
}];
回答2:
My thoughts are that this is to do with the removal being within the block of code that is running from the observer, however, I am unsure how I can resolve this (if indeed this is what the issue is).
Could someone be so kind as to explain how I can achieve this?
Certainly.
You can easily test your theory by not using the addObserverForName:object:queue:usingBlock:
method and instead using the addObserver:selector:name:object:
method, where the selector
is the name of a function you call instead of using a block.
Simply use the API guide for NSNotificationCenter for details about these methods, or in general, since you question was about what other method you could use that does not require a block statement, consulting the API is the first place to check for alternative tools within the class.
来源:https://stackoverflow.com/questions/23455956/ios-nsnotificationcenter-observer-not-being-removed