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];
}];
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 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 trying to separate my GUI and my Logic...For example, i have one class which calculates something (calc.h/calc.m). And i have my GUI (viewController.h/viewController.m)...Now i want to update one Element of the GUI from another class... I already tried it with a Singleton, like this:
calc.m:
viewController *con = [viewController sharedInstance];
con.download.text = #"It Works";
viewController.m:
+ (id)sharedInstance {
static id sharedInstance;
#synchronized(self) {
if (!sharedInstance)
sharedInstance = [[viewController alloc] init];
return sharedInstance;
}
}
But it does´t work...
UPDATE:
in my ViewController:
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(receiveNotification:)
name:#"UpdateDownloadLabel"
object:nil];
- (void) receiveNotification:(NSNotification *) notification
{
NSDictionary* userInfo = notification.userInfo;
if ([[notification name] isEqualToString:#"Update"])
{
download.text = [userInfo valueForKey:#"Test"];
}
}
And in my other class i post the notification like this:
[[NSNotificationCenter defaultCenter]
postNotificationName:#"UpdateDownloadLabel"
object:nil userInfo:info];
But it doesn't work...
That's not a proper use of a singleton. If you need to notify your UI from your model you have these options:
- delegation
- Local Notification
- KVO
The general rule is to keep your logic decoupled from your presentation, therefore your calc class shouldn't really know that a label named download exists.
Example: How to use notification.
In classA.h file
extern NSString * const ClassADidViewNotification;
In classA.m file
NSString * const ClassADidViewNotification = #"ClassADidViewNotification";
Register for notification in classA.m :-
NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
[center addObserverForName: XXFooDidBarNotification
object:nil
queue:nil
usingBlock:^(NSNotification *notification)
{
NSLog(#"notification.object: %#", notification.object);
}
];
Post Notification:-
ClassB.m
[[NSNotificationCenter defaultCenter] postNotificationName: ClassADidViewNotification object:nil];
What am I missing here? I'm just trying to send a simple notification from a modal view controller back to the view controller that launched it, but nothing gets received.
This is the code in the view controller that launches the modal segue:
- (IBAction) chooseSuperGroup:(UIButton *)sender {
NSLog(#"super group choice about to be made");
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(choiceReceived:)
name:#"selectionMade"
object:self];
}
- (void) choiceReceived: (NSNotification *) notification
{
NSLog(#"here");
if ([[notification name] isEqualToString:#"selectionMade"]) {
NSLog(#"received");
NSLog(#"%#", (NSString *)[notification userInfo]);
}
[[NSNotificationCenter defaultCenter] removeObserver:self
name: #"selectionMade"
object:self];
}
Then, over in the modal view controller, this code executes when the user selects a cell from the table view:
NSDictionary *dict = [NSDictionary dictionaryWithObject:selection forKey:#"superGroup"];
NSLog(#"printing dictionary contents");
for (id key in dict) {
NSLog(#"key: %# object: %#", key, [dict objectForKey:key]);
}
[[NSNotificationCenter defaultCenter] postNotificationName:#"selectionMade" object:self userInfo:dict];
My output looks like this:
Super group choice about to be made
printing dictionary contents
key: superGroup object: myChoice
So the choice is captured and added to a dictionary. But there is no evidence of any notification being received. This can't be that hard, but I'm not seeing my mistake. Can someone help me? Thanks!
Try using 'nil' instead of 'self'
// Add Observer
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(choiceReceived:) name:#"selectionMade" object:nil];
// Remove Observer
[[NSNotificationCenter defaultCenter] removeObserver:self
name: #"selectionMade"
object:nil];
// Post Notification
[[NSNotificationCenter defaultCenter] postNotificationName:#"selectionMade" object:nil userInfo:dict];
refer:https://stackoverflow.com/a/8188759/2449268
I think that should be here:
-(void) viewWillDisappear:(BOOL)animated
{
[super viewDidDisappear:animated];
NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
[nc removeObserver:self];
}
or maybe in -dealloc.
Both sound strange to me so I´m not totally sure of it.
First, in my AppDelegate I´m listening to a Remote Notification Via Parse
- (void)application:(UIApplication *)application
didReceiveRemoteNotification:(NSDictionary *)userInfo {
[PFPush handlePush:userInfo];
NSString * urlToGo = [userInfo objectForKey:#"url"];
NSLog (#"Recibo notificación con paremetro url: %#", urlToGo);
NSNotification *note = [NSNotification
notificationWithName:PUSH_NOTIFICATION
object:self
userInfo:userInfo];
[[NSNotificationCenter defaultCenter] postNotification:note];
}
and in myViewController
- (void) viewDidLoad {
[super viewDidLoad];
_lastMenuSelected=menu1;
NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
NSOperationQueue *mainQueue = [NSOperationQueue mainQueue];
[center addObserverForName:PUSH_NOTIFICATION
object:nil
queue:mainQueue
usingBlock:^(NSNotification *note) {
// Save in property to load parameter in prepareForSegure
_urlToLoadFromPush = urlToGoReceivedFromPush;
[self showPush:self];
}];
}
- (void)showPush:(id)sender {
PushViewController * pushViewController=(PushViewController*)[self.storyboard instantiateViewControllerWithIdentifier:#"PushId"];
pushViewController.url = _urlToLoadFromPush;
UINavigationController* nVC=[[UINavigationController alloc] initWithRootViewController:pushViewController];
[self presentViewController:nVC animated:YES completion:^{
//[_delegate logout];
}];
}
Since you seem to be adding the observer in the viewDidLoad method (which is only called once as of iOS 6), you should remove the observer in the dealloc method.
Don't remove the observer in viewWillDisappear beacause generally we require to post the notification when the view is in the stack but not appearing. So always try to remove the observers in -(void)dealloc with the name of observer.