Send notification to another view controller when request finishes - objective-c

I am working on an Iphone Application (ios5 + storyboard + arc).
I have 2 ViewControllers A and B.
In A I have a button. when pressed I am submitting a request asynchronously to the server (using AFNetworking) and I will go to View Controller B by using performSegueWithIdentifier (push not modal).
When the request finishes it executes a request successful Block that will save data to the database. (The block is in ViewController A since the request is sent from there)
Is there a way I can notify ViewController B that the request has finished and execute a method in B?
What I'm looking for is that when the request finishes and enters the Success Block I run a method in view controller B which is the loaded view.
I hope I was clear.
Thanks

For posting a notification use the below code:
[[NSNotificationCenter defaultCenter] postNotificationName:#"Midhun" object:nil];
In the viewDidLoad of the notification listening class add observer like:
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(performTask:) name:#"Midhun" object:nil];
performTask: is the method which will be called when the notification is observed.
Please refer NSNotification Class Reference

First options is to store reference to view controller B somewhere (as example in application delegate) and use it to run a method.
The second one is to send notification via [NSNotificationCenter defaultCenter], so controller B set a listener to a notification somewhere (viewDidLoad can be a good place):
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(finished:) name:#"requestfinishes" object:nil];
and controlle A sends it:
[[NSNotificationCenter defaultCenter] postNotificationName:#"requestfinishes" object:nil userInfo:nil];
Note that if you send a notification from a different thread, listener will be executed on the same thread.

Related

What happens when a nsnotification is sent to an inactive viewcontroller?

In my applicationWillEnterForeground, I check and send a notification if data refresh is necessary:
[[NSNotificationCenter defaultCenter] postNotificationName:#"refreshModelNotification" object:nil];
The only observer for that particular notification is a particular view controller:
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(refreshData:) name:#"refreshModelNotification" object:nil];
That view controller is one of several inside a UITabBarController.
My question is: what happens if that view controller isn't the active tab when the notification is sent?
Thanks in advance.
If the observer is still set for the view controller the view controller will still receive the notification and behave normally except any visual changes to the view controller's view will not be seen

nsnotification for specific object

Im working on an ios app, ios 5+ , using xcode and objective c. Ok currently messing with nsnotifications and i just need some clarifications as im a wee bit confused.
Lets say i have a view controller that i add an observer to like so
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(showContent:) name:kTPSShowContentNotification object:self];
where the object is set to self. I took this to mean that it is only looking from that notification if sent from that object. am i wrong on that?
elsewhere in code I am positing a notification like so
[[NSNotificationCenter defaultCenter] postNotificationName:kTPSShowContentNotification object:currentVC];
where currentVC is the view controller that has the observer set up initially.
I thought this is all that was needed to catch that notification as the post is telling the notification center to send it from that view controller. but it fails to catch it and im unsure as to why. If when adding the observer i set the object as nil then it catches it but so does all the other viewcontrollers (if any ) that have observers for that notification too. Is there any way around this ? am i approaching this completely wrong?
To receive notification only from theObjectSendingNotification object you should write:
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(showContent:) name:kTPSShowContentNotification object:theObjectSendingNotification];
and the object sending notification should send it in this way
[[NSNotificationCenter defaultCenter] postNotificationName:kTPSShowContentNotification object:self];
If I'm getting this right, you want to post and get a notification from the same controller. So you can do something like this:
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(showContent:) name:kTPSShowContentNotification object:self];
[[NSNotificationCenter defaultCenter] postNotificationName:kTPSShowContentNotification object:self];
But it should work indeed if your currentVC ivar is pointing to the very same controller. The fact that you say it doesn't work makes me believe that it is not pointing to the same instance of your controller.

Execute code when app reopens

I have a Single View Application. When I hit the home button and ‘minimise’ the application I want to be able to execute code when the user reopens it.
For some reason viewDidAppear and viewWillAppear do not execute when I minimise and reopen the application.
Any suggestions?
Thanks in advance
sAdam
You can either execute code in the app delegate in
- (void)applicationDidBecomeActive:(UIApplication *)application
or register to observe the UIApplicationDidBecomeActiveNotification notification and execute your code in response.
There is also the notification UIApplicationWillEnterForegroundNotification and the method - (void)applicationWillEnterForeground:(UIApplication *)application in the app delegate.
To hook up notifications add this at an appropriate point
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(didBecomeActive:)
name:UIApplicationDidBecomeActiveNotification
object:nil];
Define a the corresponding method
- (void)didBecomeActive:(NSNotification *)notification;
{
// Do some stuff
}
Then don't forget to remove yourself an observer at an appropriate point
[[NSNotificationCenter defaultCenter] removeObserver:self];
Discussion
You most likely only want your viewController to respond to events whilst it is the currently active view controller so a good place to register for the notifications would be viewDidLoad and then a good place to remove yourself as an observer would be viewDidUnload
If you are wanting to run the same logic that occurs in your viewDidAppear: method then abstract it into another method and have viewDidAppear: and the method that responds to the notification call this new method.
This is because since Apple implemented "Multitasking", apps are completely reloaded when you start them again, just as if you had never closed them. Because of this, there is no reason for viewDidAppear to be called.
You could either implement
- (void)applicationWillEnterForeground:(UIApplication *)application
and do there what ever you want. Or you register for the notification UIApplicationWillEnterForegroundNotification in your view controller. Do this in viewDidLoad:
[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(myAppWillEnterForeground)
name:UIApplicationWillEnterForegroundNotification object:nil];
And of course implement the specified selector and do there what you want.
I am not sure how the answer by #Paul.s performs the OP request since registering UIApplicationDidBecomeActiveNotification will be executed twice:
When launching the app
When application goes into the background
A better practice will be to decouple those events into 2 different notifications:
UIApplicationDidBecomeActiveNotification:
Posted when the app becomes active.
An app is active when it is receiving events. An active app can be said to have focus. It gains focus after being launched, loses focus when an overlay window pops up or when the device is locked, and gains focus when the device is unlocked.
Which basically means that all logic related to "when application launched for the first time"
UIApplicationWillEnterForegroundNotification:
Posted shortly before an app leaves the background state on its way to becoming the active app.
Conclusion
This way we can create a design that will perform both algorithms but as a decoupled way:
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(yourMethodName1) name:UIApplicationWillEnterForegroundNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(yourMethodName2) name:UIApplicationDidBecomeActiveNotification object:nil];
This because you don't redraw your view. Use applicationWillEnterForeground in the AppDelegate instead. This should work fine for you.

Adding 2 observer with one name in NSNotificationCenter in 1 class

I have a observer problem with NSNotificationCenter in my app.
My AppDelegate class has 2 service class to get data by url which called ExhibitionService & NewsService.
This 2 service class uses one Queueloader class in itself.
When I wrote 2 observer to listen service load operations in my appdelegate class, it returns error and crashes.
APP DELEGATE CLASS
ExhibitionLoaderService *exhibitionService = [[ExhibitionLoaderService alloc] init];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(exhitibionServiceComplete :) name:**CserviceComplete** object:nil];
[exhibitionService load];
NewsLoaderService *newsService = [[NewsLoaderService alloc] init];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(newsServiceComplete :) name:**CserviceComplete** object:nil];
[newsService load];
ExhibitionLoaderService.m & NewsLoaderService has the same method
-(void)load
{
Queueloader *que = [[Queueloader alloc] initWithPath:CExhibitionURLPath isVerbose:NO];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(didQueComplete:) name:CdidQueueloaderComplete object:nil];
[que startOperation];
[que release];
}
ERROR I GOT
[[NSNotificationCenter defaultCenter] postNotificationName:**CdidQueueloaderComplete** object:results];
2 service class has CdidQueueloaderComplete... Problem is about observers but how? what?
PS. Program received signal EXC_BAD_ACCESS.
Thanks.
There's no problem with having multiple observers of the same notification. The problem you describe sounds a lot like it's related to the lifetime of your observers.
If you deallocate an object that's still registered to listen to notifications, the NSNotificationCenter doesn't know about that. If a notification comes in in the future, the center will forward it to the object it thinks is still listening (but that has gone away), and you get a crash.
The solution to this problem is to ensure that your object is removed as an observer before it is destroyed. There are two ways to do this:
often you'll know when an object should start or stop listening to notifications, and you can make sure you remove it as an observer when it should stop (for example, perhaps view controllers should start listening for model updates when their views appear and stop listening when their views disappear)
other times, an object can look after its own notification lifecycle: perhaps you can start listening in an initialiser and stop listening in -dealloc.
Whatever way you do it, you need to balance adding observers and removing observers so that when an object goes away it's no longer registered with the notification center.

Calling a method when the application is called from background

In applications like Foursquare when I click the Home button the application goes to background. Then when I click on its icon, it loads back the content on the screen.
When I send my app to background and then I recall it back, it doesn't load back the content to the screen. I have entered my code in the viewDidAppear method but it is not executed.
How is it possible to load the application content when it becomes active?
You need to respond to - (void)applicationDidBecomeActive:(UIApplication *)application or - (void)applicationWillEnterForeground:(UIApplication *)application or the equivalent UIApplication notifications. The UIViewController lifecycle calls like viewDidAppear aren't triggered by app lifecycle transitions.
smparkes suggestion is right. You could register for UIApplicationDidBecomeActiveNotification or UIApplicationWillEnterForegroundNotification. These notifications are called after those method (the ones smparkes wrote) are called. In the handler for this notification do what you want. For example in viewDidLoad for your controller register the following notification:
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(doUpdate:)
name:UIApplicationDidBecomeActiveNotification object:nil];
Do not forget to remove in dealloc:
[[NSNotificationCenter defaultCenter] removeObserver:self];
Finally, doUpdate method could be the following
-(void)doUpdate:(NSNotification*)note
{
// do your stuff here...
}
I suggest you to read UIApplicationDelegate class reference. In particular read about Monitoring Application State Changes.
Hope it helps.
Suppose you want to listen to UIApplicationDidBecomeActiveNotification,here is the ObjC code that might help you.
[[NSNotificationCenter defaultCenter] addObserverForName:UIApplicationDidBecomeActiveNotification
object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *note) {
// custom code goes here.
}];