Remove a specific selector from observer - iphone

Hi I have a problem with notificationCenter. I'm launching the load of three different feeds and I'm registering three notifications with three different selector (the observer object is the same for the three notifications).
notification1 -> selector1
notification2 -> selector2
notification3 -> selector3
All works fine but I can't unregister the observer when I receive the feed content because in that case i'm blocking to receive the other two feeds. otherwise if I don't unregister the observer I'm getting the notification twice if I resend the same query with the same selector and notification name.
Are there any way to unregister just the selector without unregister the object?

- (void)removeObserver:(id)notificationObserver name:(NSString *)notificationName object:(id)notificationSender
is the method you're looking for. Just pass the correct notificationName for each case.

Related

Notifications from NotificationCenter while debugging

How can I ensure, that an observer within a NotificationCenter is called only once - especially when the app crashes/has to be stopped by Xcode?
Let's assume I want to print the notification NSNotification.WhatHaveYou.
init() {
NotificationCenter.default.addObserver(forName: NSNotification.Name.WhatHaveYou, object: nil, queue: OperationQueue.main, using: { (notification) in
print(notification)
})
}
Which works fine.
Apple stated in its documentation for NotificationCenter.default.addObserver(forName:, object:, queue:, using:):
The block to be executed when the notification is received.
The block is copied by the notification center and (the copy) held
until the observer registration is removed.
But how can I make this observer registration is removed, so that for the next app start there is no further notification registered?
Especially when the app crashes or I stop the application via Xcode, the observer is not removed, so the notification will show up multiple times - to be more precise: lastNumberOfOccurences = lastNumberOfOccurences +1
How to handle that properly?
Update
So far I find these resources
http://benscheirman.com/2012/01/careful-with-block-based-notification-handlers/
http://sealedabstract.com/code/nsnotificationcenter-with-blocks-considered-harmful/
Observers that are subscribed to NotificationCenter cannot survive app restarts. This is because the objects that you've added get removed from memory as soon as the app dies, be it a crash or a normal termination. This said, all observers need to be added during runtime of your app and they can be also removed during your app's runtime. As soon as the app terminates, all associated memory gets freed, including subscribed observers.

How to make custom notification so that whenever event occurs it will handle in iOS

Hi I want to make custom local notification so that whenever popover is visible it will handle by that notification.
so that as multiple time the popover is visible it will handle by that notification
Currently i have partially done this but problem is that if i want to run notification's selector method multiple times i have to post that notification wherever i want.
used this link to implement it
i want to send some notifications to observers when some event occurs. and i also want to know how observer catch/handle/receive that notification?
Can i make notification like, once i postNotification in viewDidLoad it will handle as many times that event occurs?
Note-See the answer posted by me
Use this
line before presenting popover
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(dissmissPop:) name:#"popOver" object:popOver.contentViewController];//popOver is your name of popover
-(void)dissmissPop:(id)sender{
//method to be called
}
To call notification from popover use this
[[NSNotificationCenter defaultCenter] postNotificationName:#"popOver" object:self];
Notifications are same as broadcast receivers. If we register as broadcast receiver whenever new email arrives. But do you actually post the event notification? No. Someone else does. Similarly when keyboard is shown the notification is posted by the system. Send you only get notified.
The system posts whenever the keyboard is gonna appear. This should make it clear that if you want to post custom notifications you have to post it every time there's need for it to.
So if you make custom notification you have to postNotification when ever you want to post it.

NSNotification in iphone sdk

what is the use of NSNotification in iphone sdk?
Thanks
I know this isn't generally a good way to answer questions, but RTFM.
NSNotification objects encapsulate information so that it can be broadcast to other objects by an NSNotificationCenter object. An NSNotification object (referred to as a notification) contains a name, an object, and an optional dictionary. The name is a tag identifying the notification. The object is any object that the poster of the notification wants to send to observers of that notification (typically, it is the object that posted the notification). The dictionary stores other related objects, if any. NSNotification objects are immutable objects.
You can create a notification object with the class methods notificationWithName:object: or notificationWithName:object:userInfo:. However, you don’t usually create your own notifications directly. The NSNotificationCenter methods postNotificationName:object: and postNotificationName:object:userInfo: allow you to conveniently post a notification without creating it first.
NSNotifications allow you to have a method called when a event occurs.
For example if you have a MPMoviePlayer and you want todo something when it is done you could use the following code:
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(movieFinished:) name:MPMoviePlayerPlaybackDidFinishNotification object:yourMoviePlayer.moviePlayer];
or if you want to do something when the device rotates:
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(orientationChanged:) name:UIDeviceOrientationDidChangeNotification object:self];
You should have a look at the Notifications section in the Cocoa Fundamentals Guide. There's anything you need to know about notifications there : from definition to use cases.
In terms of events NSNotifications are an alternative to delegation. Delegation can be used to notify one single delegate of an event, whereas notifications can be used to notify an arbitrary number of receivers. A notification is sent to the main notification center, which then notifies every object, that has registered for the notification.
One important difference is, that with delegation you can receive the delegates response to the event, whereas with NSNotifications you just send away the notification, but you don't know about the receivers or their response to the notification.
You register a UINotification when you want to receive a alert from iOS. So if you want to do something when a accessory is plugged in or a TV is plugged in you would register a UINotification for it and it would call a method in your app when the event occurs.

NSNotification race condition

Are there any race condition issues when using NSNotifications within a single thread? Here is a sample method:
- (void) playerToggled: (NSNotification *) notification {
if (timerPane.playing && ! timerPane.paused) {
[playerPane toggleCurrentPlayer];
[timerPane toggleTimer];
[mainPane playerToggled];
}
}
The first two calls after the condition will trigger NSNotifications that will be received by mainPane. Is mainPane guaranteed to receive the playerToggled message after those notifications? I should say that this code seems to work as desired (playerToggled always executes last). But I'm not sure what timing issues there are around notifications and I can't find a specific answer.
There are no race conditions to be expected. In addition to Dan Donaldson's answer, here is another quote from the docs for NSNotificationCenter:
A notification center delivers notifications to observers synchronously. In other words, the postNotification: methods do not return until all observers have received and processed the notification. To send notifications asynchronously use NSNotificationQueue.
I am not exactly sure what you mean, but I think this will be helpful to you:
http://developer.apple.com/iphone/library/documentation/Cocoa/Conceptual/Notifications/Articles/NotificationQueues.html#//apple_ref/doc/uid/20000217
Especially this part:
Using the NSNotificationCenter’s postNotification: method and its variants, you can post a notification to a notification center. However, the invocation of the method is synchronous: before the posting object can resume its thread of execution, it must wait until the notification center dispatches the notification to all observers and returns.

How should I deal with the need for multiple callbacks for the same delegate in Objective-C?

I have created a library which can download JSON data which is then placed into an NSDictionary. I wrap this class with a simple Twitter engine which allows me to pull my friends timeline, post an update and post an update with my GPS location. From my limited experience with Objective-C the way to connect everything is with delegation. I set a delegate property which calls back the asynchronous result to either a selector or a method signature. I can even create an optional or required interface on the delegate which will allow Xcode to assist me a little with implementing the delegate. To learn about using delegates in Objective-C I created this simple project.
http://www.smallsharptools.com/downloads/ObjC/Delegates.zip
It defines a Worker class which allows you to initialize the class with a delegate. When the work is done with the doWork method it looks for a method signature on the delegate to send a message back to it. It uses the following code.
if([[self delegate] respondsToSelector:#selector(workFinished:)]) {
NSString *msg = #"That's it? Easy!";
[[self delegate] workFinished:msg];
}
It looks for the workFinished: method to pass back a message. I declared this method signature as an optional interface with the following code in the header, Worker.h.
#protocol WorkerNotifications
#optional
- (void) workFinished: (NSString *) msg;
#end
You can see the rest of the project from the download for all of the details. But these 2 code snippets show how this delegation pattern works. But with the Twitter class I need to know the context of the method which started an asynchronous action which leads to a callback to a delegate method. If I call the sendUpdate method more than once from the calling class, how I am supposed to know the context of the callback?
Normally with a language like JavaScript, Java or C# I would create an inline closure or anonymous class which would have access to the starting context, but that is not possibly currently with Objective-C on the iPhone. I found that this question was already asked and answered on StackOverflow.
Anonymous delegate implementation in Objective-C?
So what I have done is skip the optional interface and instead passed in a selector which the Twitter class will call when the asynchronous action is completed. A call to start this action looks like...
CMTwitterEngine *engine = [[CMTwitterEngine alloc] initWithDelegate:self];
[engine setSendUpdateFinished:#selector(sendUpdateFinished:)];
[engine setSendUpdateFailed:#selector(sendUpdateFailed:)];
[engine setParsingSendUpdateFailed:#selector(parsingSendUpdateFailed:)];
[engine setUsername:TWITTER_USERNAME pass:TWITTER_PASSWORD];
[engine sendUpdate:statusUpdateText.text];
This code first initializes the engine reference with self as the delegate. To attach the callbacks I send in selectors which I originally had on the sendUpdate method signature but the method calls got pretty long. I opted to simply set properties of the selectors. This all works but I am not sure I like how this is working since it only partially solves my problem.
To complete this example, I finish the asynchronous work and eventually call a method internally which looks for the given selector and calls it if it is defined.
- (void)sendUpdateFinished:(NSDictionary *)dictionary {
if (self.sendUpdateFinished != nil) {
[self.delegate performSelector:self.sendUpdateFinished withObject:dictionary];
}
}
I can pass in the status message to send as a Twitter update but I still do not have the context of the originating call. What if I want to call sendUpdate more than once and the first asynchronous call is still running? And what if the second call finishes first? They will both have self as the delegate so I would have to either track the context somehow or pass them to a different selector to distinguish them, which also does not satisfy my needs. What happens if I have 3 or 4 or 5 asynchronous calls? I need to know which ones were sent successfully and when they are complete.
It appears the only way that I can do all this is to create a class which holds onto all of the properties needed for the context, have that class act as the delegate for the call to the asynchronous Twitter method and then report back to the parent class which is likely UIViewController. I would take this approach but I have not read about this approach or seen any sample code yet which does this.
What would you do? How would you handle multiple asynchronous calls going out which could end in a different order than going out and then process them with context upon completion?
I think your situation is a great place to use NSNotificationCenter
http://developer.apple.com/iphone/library/documentation/Cocoa/Reference/Foundation/Classes/NSNotificationCenter_Class/Reference/Reference.html
I have to second (or third) the previously posted answers in that NSNotificationCenter is probably what you're looking for here.
Essentially one typically uses notifications when there are potentially many delegates all of which need to do something in response to a single action or event that has occurred. Think of it as a one-to-many sort of delegation or an implementation of the observer pattern. The basic things to know are:
NSNotifications have a name that you define which is just an NSString. Notifications can be posted by name and objects register to receive notifications by name.
When a notification is posted a notificationSender object and/or userInfo dictionary can be provided. The notificationSender is the direct way of determining who posted a given notification when it is being handled by the receiver. The userInfo is an NSDictionary that can be used to provide additional context info along with the notification.
So, rather than forcing all of the workers to adopt to an informal protocol and messing around with reflection style calling-methods-at runtime you just register instances of the workers with NSNotificationCenter. Typically the registration with the NSNotificationCenter is done in an init method of each worker class. Instances of each type of worker are then typically set up as "freeze dried" objects in a NIB or can be programatically instantiated in the app delegate so that they get registered with the notification center early on in the app's life.
When the thing occurs you post a NSNotification to the NSNotificationCenter (which is essentially a singleton) and then everything else that has registered to receive that particular type of notification will have the method called that was specified to handle that type of notification. When done these methods can then call a common method back on the sender (obtained via NSNotification's object method) to tell the sender that they've completed their work.
Once each known worker has checked in the the common method on the sender can then go on to whatever post-worker-completion code is to be performed.
One thing to consider is using Notifications instead. Simplifies code, couples things less tightly.