I have an UIActivityIndicatorView which I start and stop on an notification which I receive from the Notification Center. Although I receive the notifications and I call the start and stop via 'performSelectorOnMainThread' it does not start animating, and does not become visible.
Here is my code:
-(void)stopAnimation:(id)sender {
if( _saveActivityIndicatorView.isAnimating ) {
[_saveActivityIndicatorView stopAnimating];
}
}
-(void)startAnimation:(id)sender {
if( !_saveActivityIndicatorView.isAnimating ) {
[_saveActivityIndicatorView startAnimating];
}
}
-(void)saveStarted{
NSLog(MRVaccinationEventsUpdateStarted);
[self performSelectorOnMainThread:#selector(startAnimation:) withObject:self waitUntilDone:YES];
}
-(void)saveCompleted{
NSLog(MRVaccinationEventsUpdateCompleted);
[self performSelectorOnMainThread:#selector(stopAnimation:) withObject:self waitUntilDone:YES];
}
And this is how I post and observe the notifications (both in the same file):
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(saveStarted)
name:MRVaccinationEventsUpdateStarted
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(saveCompleted)
name:MRVaccinationEventsUpdateCompleted
object:nil];
[[NSNotificationCenter defaultCenter] postNotificationName:MRVaccinationEventsUpdateStarted object:nil];
[[NSNotificationCenter defaultCenter] postNotificationName:MRVaccinationEventsUpdateCompleted object:nil];
Note, that I DO RECEIVE the notifications.
What is wrong with this code?
This is because the start and stop animation's are in the same loop.
[[NSNotificationCenter defaultCenter] postNotificationName:MRVaccinationEventsUpdateStarted object:nil];
[[NSNotificationCenter defaultCenter] postNotificationName:MRVaccinationEventsUpdateCompleted object:nil];
You should post the second notification after some time, like
/// three seconds
delayInSeconds = 3;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
[[NSNotificationCenter defaultCenter] postNotificationName:MRVaccinationEventsUpdateCompleted object:nil];
});
Related
I can't get the NSMetadataQueryDidUpdateNotification to work. Been stuck at it for days. Is there something abnormal in the code below.
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0ul), ^{
NSString* filePattern = [NSString stringWithFormat:#"*.%#", #"*"];
NSMetadataQuery *aQuery = [[NSMetadataQuery alloc] init];
aQuery.predicate = [NSPredicate predicateWithFormat: #"%K LIKE %#", NSMetadataItemFSNameKey, filePattern];
[aQuery setSearchScopes:#[NSMetadataQueryUbiquitousDataScope]];
[aQuery setValueListAttributes:#[NSMetadataUbiquitousItemPercentDownloadedKey, NSURLUbiquitousItemDownloadingStatusKey,NSURLUbiquitousItemIsDownloadingKey,NSURLUbiquitousItemDownloadRequestedKey]];
_query = aQuery;
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(liveUpdate:)
name:NSMetadataQueryDidUpdateNotification
object:aQuery];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(initalGatherComplete:) name:NSMetadataQueryDidFinishGatheringNotification object:aQuery];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(gatherProgress:) name:NSMetadataQueryGatheringProgressNotification object:aQuery];
[aQuery enableUpdates];
dispatch_async(dispatch_get_main_queue(), ^{
[aQuery startQuery];
});
});
Hope this helps you
Try replace with this code about notification
And metadata query should be started on main queue, you did it right :)
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(liveUpdate:)
name:NSMetadataQueryDidUpdateNotification
object:aQuery];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(initalGatherComplete:)
name:NSMetadataQueryDidFinishGatheringNotification
object:aQuery];
And this is example for processing gathering notification
- (void)initialGatherComplete:(NSNotification*)notification
{
//process here.
}
The solution is to strong reference the notification block as such
_notifqueryDidUpdate = [[NSNotificationCenter defaultCenter]addObserverForName:NSMetadataQueryDidUpdateNotification object:aQuery queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification * _Nonnull note) {
[self liveUpdate:note];
}];
I am using NSNotificationCenter in a code .
[[NSNotificationCenter defaultCenter]addObserverForName:#"NextIndexNotification" object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *note) {
[self receiveTestNotification:note];
[[NSNotificationCenter defaultCenter] removeObserver:note];
}];
- (void)receiveTestNotification:(NSNotification *) notification
{
NSDictionary *userInfo = notification.userInfo;
NSString *strServerResultID = [userInfo objectForKey:#"valServerResultID"];
}
//// And I am adding Notification center here ...
dispatch_async(dispatch_get_main_queue(),^{
NSDictionary *userInfo = [NSDictionary dictionaryWithObject:[NSString stringWithFormat:#"%#",[[PerformXMLXPathQuery(responseData,xPathQuery) objectAtIndex:0] valueForKey:kNodeContent]] forKey:#"valServerResultID"];
[[NSNotificationCenter defaultCenter] postNotificationName:#"NextIndexNotification" object:self userInfo:userInfo];
});
in this code , remove notification doesn't being called and my code move to infinite loop .
where am I doing wrong ?
Try
[[NSNotificationCenter defaultCenter] removeObserver:nil];
Remove notification by using blocks.
[[NSNotificationCenter defaultCenter] removeObserver:self];
Instead of passing note (which is the Notification itself, not the observer), pass the return value from the addObserverForName call to removeObserver, like this:
__block id observer = [[NSNotificationCenter defaultCenter] addObserverForName:#"NextIndexNotification"
object:nil
queue:[NSOperationQueue mainQueue]
usingBlock:^(NSNotification *note)
{
[self receiveTestNotification:note];
[[NSNotificationCenter defaultCenter] removeObserver:observer];
}];
I am trying to do a notification from a location manager object to my viewController. It's not working - the selector in the addObserver method doesn't get called.
Location Manager Object.m files (singleton with standard dispatch once & init methods)
- (void)setCurrentLocation:(CLLocation *)currentLocation
{
if (!_location) {
_location = [[CLLocation alloc] init];
}
_location = currentLocation;
NSNumber *latitude = [NSNumber numberWithDouble:self.location.coordinate.latitude];
NSNumber *longitude = [NSNumber numberWithDouble:self.location.coordinate.longitude];
NSLog(#"lat %# & long %# in notification section", latitude, longitude);
NSNotification *notification = [NSNotification notificationWithName:#"myNotification" object:self userInfo: #{kSetLat: latitude,
kSetLong: longitude}];
[[NSNotificationCenter defaultCenter] postNotification:notification];
}
ViewController.m (garden variety)
- (IBAction)welcomeNotification:(UIButton *)sender {
NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
[center addObserver:self selector:#selector(sendGetRequest:) name:#"myNotification" object:[LPLocationManager sharedManager]];
[center removeObserver:self];
NSLog(#"welcomeNotication triggered");
}
The way you do is not correct. Why you add the observer and then remove it immediately. Most of the time, we add/remove observer in viewWillAppear and viewWillDisappear or viewDidAppear and viewDidDisappear.
It should be something like:-
-(void)viewWillAppear:(BOOL)animated{
[super viewWillAppear:animated];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(sendGetRequest:) name:#"myNotification" object:nil];
}
-(void)viewWillDisappear:(BOOL)animated{
[super viewWillDisappear:animated];
[[NSNotificationCenter defaultCenter] removeObserver:self name:#"myNotification" object:nil];
}
I am using MPMoviePlayerViewController to play a movie , I create a method which should detects when movie is finished then run a method :
- (void)movieFinishedWithSelector:(SEL)selectors {
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(selectors)
name:MPMoviePlayerPlaybackDidFinishNotification
object:[player moviePlayer]];
}
and use this method like this , but does not work .
[self movieFinishedWithSelector:#selector(finished)];
Am I missing something ?
The selectors parameter is already a selector. Don't use #selector:
- (void)movieFinishedWithSelector:(SEL)selector {
[[NSNotificationCenter defaultCenter] addObserver:self
selector:selector
name:MPMoviePlayerPlaybackDidFinishNotification
object:[player moviePlayer]];
}
create a notication when you load the movie
[[NSNotificationCenter defaultCenter]addObserver:self selector:#selector(myMovieFinished:) name:MPMoviePlayerPlaybackDidFinishNotification object:movieController];
When finished the myMovieFinished will be called
-(void)myMovieFinished:(NSNotification *)aNotification
{
NSLog(#"%#",aNotification.userInfo);
int reason = [[[aNotification userInfo]valueForKey:MPMoviePlayerPlaybackDidFinishNotification]intValue];
if (reason==MPMovieFinishReasonPlaybackEnded) {
NSLog(#"Movie finished playing");
}
else if (reason==MPMovieFinishReasonUserExited)
{
NSLog(#"Movie finished because user exited");
}
else if (reason==MPMovieFinishReasonPlaybackError)
{
NSLog(#"movie finished playback error");
}
movieController=[aNotification object];
[[NSNotificationCenter defaultCenter]removeObserver:self name:MPMoviePlayerPlaybackDidFinishNotification object:movieController ];
}
how did you define the selector? It should be:
- (void)movieDidFinish:(NSNotification*)notification
Is there any corner case behaviors for removeObserver:name:object:? In the following block of code, my observer isn't being registered properly:
- (void)setPlayerItem:(AVPlayerItem *)playerItem {
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(playerItemDidReachEnd:)
name:nil
object:playerItem];
[playerItem addObserver:self
forKeyPath:kStatus
options:0
context:(__bridge void*)self];
[playerItem addObserver:self
forKeyPath:kPlaybackBufferEmpty
options:0
context:(__bridge void*)self]; // For adding a buffering activity indicator
id temp = playerItem_;
playerItem_ = [playerItem retain];
[[NSNotificationCenter defaultCenter] removeObserver:self name:nil object:temp];
[temp removeObserver:self forKeyPath:kPlaybackBufferEmpty];
[temp removeObserver:self forKeyPath:kStatus];
[temp release];
}
However, if I change the order around to:
- (void)setPlayerItem:(AVPlayerItem *)playerItem {
[playerItem addObserver:self
forKeyPath:kStatus
options:0
context:(__bridge void*)self];
[playerItem addObserver:self
forKeyPath:kPlaybackBufferEmpty
options:0
context:(__bridge void*)self]; // For adding a buffering activity indicator
id temp = playerItem_;
playerItem_ = [playerItem retain];
[[NSNotificationCenter defaultCenter] removeObserver:self name:nil object:temp];
[temp removeObserver:self forKeyPath:kPlaybackBufferEmpty];
[temp removeObserver:self forKeyPath:kStatus];
[temp release];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(playerItemDidReachEnd:)
name:nil
object:playerItem];
}
All the notifications post just fine. This leads me to believe something strange is happening when I call:
[[NSNotificationCenter defaultCenter] removeObserver:self name:nil object:temp];
Am I missing something really obvious here? I'm on iOS 6 with no ARC.
Found the answer. Turns out it has to do with passing in nil for the observer name.
Calling [[NSNotificationCenter defaultCenter] removeObserver:self name:nil object:temp];
will remove self from observing any notifications posted by temp.
However, in the corner case that temp is nil, this line of code will remove self as an observer all together.
Name shouldn't be nil. Did you try giving your observer a name?
#Lee is correct that the name should not be nil but it also should not be the name of the observer. Rather it should be the name of the notification that you are registering to observe. e.g., UIDeviceOrientationDidChangeNotification.
Add the name of the notification that you want to observe in that param and also pass it as the name param when you remove observer