I am trying to find what delegate/protocol or even notification is called when an alert view is hidden or shown. Do these events trigger a notification or callback that I can listen for?
I know the UIAlertView protocol, but that's not what I am looking for, I am looking for the actual display and hide events to perform actions after they are completed.
Does this exist?
If you want to know about AlertViews you've presented yourself, you're looking for UIAlertViewDelegate protocol
didPresentAlertView: and alertView:didDismissWithButtonIndex:
If you want to know when an AlertView has been shown by the OS, you can try UIWindowDidBecomeVisibleNotification and UIWindowDidBecomeHiddenNotification in the UIWindow class reference, then check if the windowLevel property is equal to UIWindowLevelAlert
An easy way to check NSNotifications is adding that code to your AppDelegate.m:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(notification:) name :nil object:nil];
return YES;
}
-(void)notification:(NSNotification*)notification
{
NSLog(#"Notification name is %#, \n sent by %#\n\n",[notification name], [[notification object] description] );
}
I tested this code triggering UIAlertViews and I never receive an NSNotification related to.
So probably there aren't NSNotificationrelated to UIAlertViews.
Related
In my iOS application, I'm having a UITableView inside my UIViewController. After data loading completed to the UITableView, when I press the Home button of the iPhone, the application will enter to the background. It will execute following method.
- (void)applicationDidEnterBackground:(UIApplication *)application {
When I tap on the application icon and launch the app, it will call following methods in AppDelegate
- (void)applicationWillEnterForeground:(UIApplication *)application {
and
- (void)applicationDidBecomeActive:(UIApplication *)application {
but none UIViewController methods. Therefore what I did was, called a custom method created by myself which is located inside my UIViewController class like below. This code go inside applicationDidBecomeActive method.
MyViewController *tViewCont = [MyViewController alloc];
[tViewCont remindToPopulate];
I put a log message and confirmed that remindToPopulate method is executing. Inside that method I want to reload the UITableView.
But at this time the UITableView property that I've declared is set to nil. What is the proper way of saving that UITableView property and load it back with the latest data?
For that you can add notification for UIApplicationDidBecomeActiveNotification or UIApplicationWillEnterForegroundNotification in viewDidLoad in controller.
just add
[[NSNotificationCenter defaultCenter]addObserver:self selector:#selector(yourmethod) name:UIApplicationDidBecomeActiveNotification object:nil];
and in yourmethod
-(void)yourmethod{
[yourtableview reloadData];
}
you can also add UIApplicationWillEnterForegroundNotification notification. add as per your need.
I have referred the following links for this issue, but neither of the solutions worked for me:
Link 1
Link 2
I think these solutions don't work for iOS7.
So now how would I be able to find out whether there is any UIAlertView open, when my application enters in background state.
I want to dismiss the UIAlertView before going into the background.
Remove alert in applicationDidEnterBackground
Add this line in your class
[[NSNotificationCenter defaultCenter] addObserver: self
selector: #selector(enteredBackground:)
name:UIApplicationDidEnterBackgroundNotification
object: nil];
And implement method as well
- (void)enteredBackground:(UIApplication *)application
{
if (mainAlertView && mainAlertView.isVisible)
[mainAlertView dismissWithClickedButtonIndex:0 animated:NO];
}
You get a notification when the app is send to background, so detect that notification in the class that displays the alert view and remove it, that's all
have you checked UIAlertView property #property(nonatomic, readonly, getter=isVisible) BOOL visible Also while going in the background you get a notification in - (void )applicationDidEnterBackground: you can check there and remove all alertviews if any
I want to send an NSNotification from this method (when the UIButton is clicked) in my AppDelegate.m:
- (void)alertView:(UIAlertView *)alertView
clickedButtonAtIndex:(NSInteger)buttonIndex{
if (buttonIndex == 0){
//cancel clicked ...do your action
// HERE
}
}
..and receive it in one of my UIViewControllers. How can I do that?
EDIT WITH MORE INFO: I am making an alarm app, and when the user presses the UIButton, I want to stop the alarm. I figured that NSNotifications is the only way to get information from my AppDelegate.m file to a ViewController.m file?
You should to register your receiver object to accept some messages sent from Notification Center.
Suppose you have Obj A which controls your alarm, and value "stopAlarm" is the message which can stop alarm. You should create an observer for a "stopAlarm" message.
You can do, with:
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(controller:)
name:#"stopAlarm"
object:nil];
Now, you should create a method controller that manages this messages:
- (void)controller:(NSNotification *) notification {
if ([[notification name] isEqualToString:#"stopAlarm"]){
//Perform stop alarm with A object
}
}
Finally, you can send the message "stopAlarm" when you want in the code with:
[[NSNotificationCenter defaultCenter]
postNotificationName:#"stopAlarm"
object:nil];
I Hope this may help.
EDIT:
When your UIViewController are unloaded or when app terminate, you should call:
[[NSNotificationCenter defaultCenter] removeObserver:self];
for stop observing.
That's all.
Thanks to Hot licks for correction.
You may want to create a class–maybe even a singleton if there is only one alarm–that manages the timer. That way you can manage from any place in your application rather than in the view controller. Take a look at:
http://dadabeatnik.wordpress.com/2013/07/28/objective-c-singletons-an-alternative-pattern/
and:
https://developer.apple.com/library/mac/documentation/cocoa/conceptual/Notifications/Articles/NotificationCenters.html
As Hot Licks mentioned, you really do not want to jump into this without knowing what is going on. Hopefully these links will help get you going in the right direction.
App delegate:
- (void)applicationDidBecomeActive:(UIApplication *)application {
[[NSNotificationCenter defaultCenter] postNotificationName:APP_REFRESH_NOTIFICATION object:nil];
}
In my view controller:
- (void)viewDidLoad {
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(doStuff) postNotificationName:APP_REFRESH_NOTIFICATION object:self];
}
- (void)doStuff never gets called. Why?
I assume that you've typed your question incorrectly and you'd meant to write addObserver:selector:name:object:, instead of addObserver:selector: postNotificationName:object: (such method doesn't exist).
In the documentation of - (void)addObserver:(id)notificationObserver selector:(SEL)notificationSelector name:(NSString *)notificationName object:(id)notificationSender
we can read:
notificationSender
The object whose notifications the observer wants
to receive; that is, only notifications sent by this sender are
delivered to the observer. If you pass nil, the notification center
doesn’t use a notification’s sender to decide whether to deliver it to
the observer.
So in your case, as you're passing object:nil in postNotificationName:object:, you also have to set object:nil in addObserver:selector:name:object:.
According to the documentation you also should replace the method doStuff with:
- (void)doStuff:(NSNotification *)notification
and use #selector(doStuff:) in addObserver:selector:name:object:.
You're passing self as the object parameter to addObserver:selector:name:object:, but doStuff doesn't accept any parameters, so the method call fails (silently). Your viewDidLoad should look like this:
- (void)viewDidLoad {
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(doStuff)
name:APP_REFRESH_NOTIFICATION
object:nil];
}
You're app delegate is posting a notification when the app becomes active, but your view controller isn't subscribing to that until its view gets loaded. If your app delegate is creating your view controller and loading it (which is probable) then your controller doesn't even exist at the time the notification is posted, which is why it isn't receiving it. If you use a storyboard, and that controller is the entry point in the storyboard, AND you use the info.plist for your app to set that storyboard as the main interface, then it will have already instantiated the controller and loaded its view by the time -applicationDidBecomeActive: is called, solving your problem.
For test purposes I've created an application with UITabBar, 3 view controllers and my class DataAnalyzer (till now it analyses nothing:)).
TestAppDelegate.m
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
//.....
NSArray *allControllers = [self.tabBarController viewControllers];
NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
for (UIVideoEditorController * viewController in allControllers) {
[center addObserver:viewController selector:#selector(useUpdatedData:) name:#"dataUpdated" object:nil];
NSLog(#"%#", [viewController description]);
}
DataAnalizer *dataAnalizer = [[DataAnalizer alloc] init];
[center addObserver:dataAnalizer selector:#selector(useUpdatedData:) name:#"dataUpdated" object:nil];
// dataAnalizer can't be released here? Where should it be done?
return YES;
}
in 2-nd, 3-rd view controllers and DataAnalyzer class I added the same method
- (void) useUpdatedData:(NSNotification *)note {
NSLog(#"Notificatio received in *** view controller");
//do something with [note object] like show it on a label or store it to instance variable
}
in 1-st view controller I added text field to send a string as notification
- (void)textFieldDidEndEditing:(UITextField *)textField {
NSLog(#"First viewController textFieldDidEndEditing: value is %# ", textField.text);
NSNotificationCenter *note = [NSNotificationCenter defaultCenter];
[note postNotificationName:#"dataUpdated" object:textField.text];
}
When I send a string, I see NSLog message in console that notification is received, but can do nothing with the string like showing it on a label. I understand that it's because a view controllers load first time and they were not initiated. But why I'm getting NSLog message in console? Can I send a string to dataAnalizer class, do something there and then get a result to second and third view controllers?
Thank you in advance for your answers, because it seems all above is a wrong approach.
Apple documentation pretty clearly states that NSNotificationCenter does not retain it's observers, thats why you can't release the dataAnalyzer there - it would be dealloc'd and the notification would attempt to post to a nil reference.
I don't think it's a good idea to loop through an array of controllers and subscribe each one to a notification. The controller isn't guaranteed to be created at that point, and because it doesn't know it's been volunteered to answer a notification it also doesn't know to unsubscribe. Instead, subscribe to the notification(s) in the -init method of each view controller. That ensures the controller has been created and initialized, and makes each controller responsible for it's own actions.
I'm not entirely sure what your question is, could you rephrase it if the above didn't resolve your problem.
Also, be aware NSNotificationCenter will post to all observers, but it is not async - it waits for each one to finish processing the notification before sending to the next object.
You don't use correctly postNotification method. Your application data should be send using userinfo parameter with the method postNotificationName:object:userInfo: