Notification does not work in Presentviewcontroller objective-c - objective-c

I am displaying a UIAlertController when I receive a response from API. After the response, I want to call the notification of other view controller.
I added observer in view controller 1 as below:
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(UpdateAthleteDictionaryNotification:) name:#"UpdateAthleteDictionary" object:self.dictProfile];
In view controller 2 my code is below:
UIAlertController * alert = [UIAlertController
alertControllerWithTitle:applicationName
message:[jsonObject valueForKey:#"responseMessage"]
preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction* yesButton = [UIAlertAction
actionWithTitle:#"Ok"
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {
dispatch_async(dispatch_get_main_queue(), ^{
[[NSNotificationCenter defaultCenter] postNotificationName:#"UpdateAthleteDictionary" object:self.dictProfile];
});
[self.navigationController popViewControllerAnimated:YES];
}];
[alert addAction:yesButton];
[self presentViewController:alert animated:YES completion:nil];
But it does not call. So please can you suggest me the solutions.

NSNotificationCenter will deliver your notification only in case if name and object are the same (source).
If you want to receive notifications with any object attached you should pass nil as an object argument, in your case:
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(UpdateAthleteDictionaryNotification:) name:#"UpdateAthleteDictionary" object:nil];

Related

How to handle multiple alerts firing at the same time

I have multiple nsnotificationcenters running at one time that display an alert when triggered. At times, this causes more than one alert to fire at a time but of course you can only display one and the other does not appear. What is the best way handle this situation so multiple alerts can go in succession.
I have tired having the alerts in one method and when one alert is showing, put another notification in an array and then run through that array but that is not working correctly. I have also tried to have the alerts in separate methods but that is not working either.
I have looked at using semaphores but could not find a good example.
This is my notifications which works as expected. I was looking for some advice on the notifications also. Where would be the best place to add the observer, in the viewDidAppear of viewDidLoad. viewDidLoad give a warning whenever an alert is displayed because it wants to display on a view that is not in the hierarchy.
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
// * 26 APR 2019 * 1.0.4.0
// Add observer for notifications
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(receivedNotification:) name:#"ROC" object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(receivedNotification:) name:#"ROP" object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(receivedNotification:) name:#"CARGO" object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(receivedNotification:) name:#"PAX" object:nil];
}
This is my selector method using a single method for all of the alerts. I am new to coding so I am sure this is not good practice so any advice would be appreciated. I am trying to put any additional notifications in an array if the current view is a uialertcontroller and then run through the array and display those alerts after but that is not working how i would like it to.
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
// * 26 APR 2019 * 1.0.4.0
// Add observer for notifications
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(receivedNotification:) name:#"ROC" object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(receivedNotification:) name:#"ROP" object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(receivedNotification:) name:#"CARGO" object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(receivedNotification:) name:#"PAX" object:nil];
}
- (void)receivedNotification:(NSNotification *)notification {
NSMutableDictionary *msgData = [[FlightDataInput sharedFlightDataInput] dataForPage:4];
NSMutableArray *alertArray = [[NSMutableArray alloc] init];
if([self.presentedViewController isKindOfClass:[UIAlertController class]]) {
[alertArray addObject:notification];
}
if(![self.presentedViewController isKindOfClass:[UIAlertController class]] && [alertArray count] == 0) {
if([notification.name isEqualToString: #"ROC"]) {
UIAlertController *alertRoc = [UIAlertController alertControllerWithTitle:[msgData valueForKey:#"rocTitle"] message:[msgData valueForKey:#"rocMsg"] preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *ok = [UIAlertAction actionWithTitle:#"OK" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action){
[alertRoc dismissViewControllerAnimated:YES completion:nil];
}];
[alertRoc addAction:ok];
[self presentViewController:alertRoc animated:NO completion:nil];
}
if ([notification.name isEqualToString:#"ROP"]) {
UIAlertController *alertRop = [UIAlertController alertControllerWithTitle:[msgData valueForKey:#"ropTitle"] message:[msgData valueForKey:#"ropMsg"] preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *ok = [UIAlertAction actionWithTitle:#"OK" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action){
[alertRop dismissViewControllerAnimated:YES completion:nil];
}];
[alertRop addAction:ok];
[self presentViewController:alertRop animated:NO completion:nil];
}
if ([notification.name isEqualToString:#"CARGO"]) {
UIAlertController *alertCargo = [UIAlertController alertControllerWithTitle:[msgData valueForKey:#"cargoTitle"] message:[msgData valueForKey:#"cargoMsg"] preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *ok = [UIAlertAction actionWithTitle:#"OK" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action){
[alertCargo dismissViewControllerAnimated:YES completion:nil];
}];
[alertCargo addAction:ok];
[self presentViewController:alertCargo animated:NO completion:nil];
}
if ([notification.name isEqualToString:#"PAX"]) {
UIAlertController *alertPax = [UIAlertController alertControllerWithTitle:[msgData valueForKey:#"paxTitle"] message:[msgData valueForKey:#"paxMsg"] preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *ok = [UIAlertAction actionWithTitle:#"OK" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action){
[alertPax dismissViewControllerAnimated:YES completion:nil];
}];
[alertPax addAction:ok];
[self presentViewController:alertPax animated:NO completion:nil];
}
}
if([alertArray count] > 0) {
for(int i = 0; i < [alertArray count]; i++) {
// creating the same alerts in here if there are alerts in the array
}
}
}
I have multiple nsnotificationcenters running at one time that display an alert when triggered. At times, this causes more than one alert to fire at a time but of course you can only display one and the other does not appear. What is the best way handle this situation so multiple alerts can go in succession.
I have tired having the alerts in one method and when one alert is showing, put another notification in an array and then run through that array but that is not working correctly. I have also tried to have the alerts in separate methods but that is not working either.
Hi you can present only one Alert at a time. if you want more in chain so first dismiss exist Alerts. Here is Sample please check and update.
{
NSMutableDictionary *msgData;
NSMutableArray <NSNotification *> *alertArray;
int alertIndex;
}
- (void)viewDidLoad:(BOOL)animated {
[super viewDidLoad:animated];
// * 26 APR 2019 * 1.0.4.0
// Add observer for notifications
msgData = [[FlightDataInput sharedFlightDataInput] dataForPage:4];
alertArray = [NSMutableArray new];
alertIndex = 0;
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(receivedNotification:) name:#"ROC" object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(receivedNotification:) name:#"ROP" object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(receivedNotification:) name:#"CARGO" object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(receivedNotification:) name:#"PAX" object:nil];
}
- (void)receivedNotification:(NSNotification *)notification {
[alertArray addObject:notification];
if(![self isAlertExist]) {
[self checkAlerts];
}
}
-(void) checkAlerts
{
if(alertIndex < [alertArray count])
{
NSNotification *notification = (NSNotification *)[alertArray objectAtIndex:arrayIndex];
arrayIndex = arrayIndex + 1;
if([notification.name isEqualToString: #"ROC"]) {
[self showAlertWithTitle:[msgData valueForKey:#"rocTitle"] andMessage:[msgData valueForKey:#"rocMsg"]];
}
else if ([notification.name isEqualToString:#"ROP"]) {
[self showAlertWithTitle:[msgData valueForKey:#"ropTitle"] andMessage:[msgData valueForKey:#"ropMsg"]];
}
else if ([notification.name isEqualToString:#"CARGO"]) {
[self showAlertWithTitle:[msgData valueForKey:#"cargoTitle"] andMessage:[msgData valueForKey:#"cargoMsg"]];
}
else if ([notification.name isEqualToString:#"PAX"]) {
[self showAlertWithTitle:[msgData valueForKey:#"paxTitle"] andMessage:[msgData valueForKey:#"paxMsg"]];
}
}
}
-(void) showAlertWithTitle:(NSString *)title andMessage:(NSString *)message
{
UIAlertController *alertPax = [UIAlertController alertControllerWithTitle:title message:message preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *ok = [UIAlertAction actionWithTitle:#"OK" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action){
[alertPax dismissViewControllerAnimated:YES completion:^{
[self checkAlerts];
}];
}];
[alertPax addAction:ok];
[self presentViewController:alertPax animated:NO completion:nil];
}
-(BOOL) isAlertExist {
for (UIWindow* window in [UIApplication sharedApplication].windows) {
if ([window.rootViewController.presentedViewController isKindOfClass:[UIAlertController class]]) {
return YES;
}
}
return NO;
}

`UIAlertController` is not triggered in NSNotification response

This is my AlertView code :
- (void)initializeAlertControllerForOneButtonWithTitle:(NSString *)title withMessage:(NSString *)msg withYesButtonTitle:(NSString *)yesButtonTitle withYesButtonAction:(id)yesButtonAction
{
UIAlertController * alert = [UIAlertController
alertControllerWithTitle:title
message:msg
preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction* yesBtn = [UIAlertAction
actionWithTitle:yesButtonTitle
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {
if (self.activityIndicator.animating) {
[self.activityIndicator stopAnimating];
}
if ([title isEqualToString:#"Wrong Password!"]) {
self.editTextField.text = #"";
[self.editTextField becomeFirstResponder];
}
}];
[alert addAction:yesBtn];
[self presentViewController:alert animated:YES completion:nil];
}
I am trying to fire this alert in my NSNotificatoin Response method. My Notification Response code :
- (void)receiveSMSVerificationResponse:(NSNotification *)notification
{
SMSVerificationDigitClassModel *smsVerificationDigitClassModel = [[SMSVerificationDigitClassModel alloc] init];
smsVerificationDigitClassModel = [notification object];
if (smsVerificationDigitClassModel.viewControllerName == ViewControllerNameProfileInfoEditViewController) {
if ([self alreadyRegisteredPhoneNumber:smsVerificationDigitClassModel.phoneNumber] == YES) {
NSLog(#"jogajog");
[self initializeAlertControllerForOneButtonWithTitle:#"Already Registered!" withMessage:kAlreadyRegisteredPhoneNumberMSGForChangePhoneNumber withYesButtonTitle:#"Ok" withYesButtonAction:nil];
} else {
if ([AdditionalClasses internetConnectionCheck] == YES) {
self.userModelClass.phone_number = smsVerificationDigitClassModel.phoneNumber;
[self updateUserModel:self.userModelClass];
} else {
[self noInternetConnectionAlert];
}
}
//Check if that phone number is already used
// udate phone numner in server
// update phone number in core data
//[self goToSignUpViewControllerWithPhoneNumber:smsVerificationDigitClassModel.phoneNumber];
}
}
I check it from break point, this line [self initializeAlertControllerForOneButtonWithTitle:#"Already Registered!" withMessage:kAlreadyRegisteredPhoneNumberMSGForChangePhoneNumber withYesButtonTitle:#"Ok" withYesButtonAction:nil]; is actually calling, but the alert view is not popping up. It says:
"Warning: Attempt to present on whose view is not in the window hierarchy!"
I have tried to add notification observer methods :
- (void)addNotificationObserver
{
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(receiveUserModelResponse:) name:#"sendUpdateRequestToServerForPhoneNumberWithUserModel" object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(receiveSMSVerificationResponse:) name:#"SMSVerificationForPhoneNumber" object:nil];
}
In viewDidLoad, viewDidAppear & in viewWillAppear and removeObserver in dealloc,
- (void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillShowNotification object:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillHideNotification object:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self name:#"sendUpdateRequestToServerForPhoneNumberWithUserModel" object:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self name:#"SMSVerificationForPhoneNumber" object:nil];
}
but it is not showing at all. So, how do I change my window hierarchy! in this viewController. If you understand, please reply back. A lot of thanks in advance.
Call the initializeAlertControllerForOneButtonWithTitle method inside a main queue dispatch queue block.
All UI operation should be on main threat.
dispatch_async(dispatch_get_main_queue(), ^{
[self initializeAlertControllerForOneButtonWithTitle:#"Already Registered!" withMessage:kAlreadyRegisteredPhoneNumberMSGForChangePhoneNumber withYesButtonTitle:#"Ok" withYesButtonAction:nil];
});

UIAlertController automatically dismisses in iOS 10

I have a UIAlertController in my AppDelegate and present it with my rootViewController when I receive a notification. But when the alert view pops up, it quickly dismisses itself instead of waiting for a tap event on the "Ok" button... Here's my code in AppDelegate.m. Any idea? Thanks!
- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification {
[self showNotification:"Success message here"];
}
- (void)showNotification:(NSString *)text {
UIAlertController* avc = [UIAlertController alertControllerWithTitle:#"Success" message:text
preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *ok = [UIAlertAction actionWithTitle:#"Ok" style:UIAlertActionStyleCancel handler:nil];
[avc addAction:ok];
[self.window.rootViewController presentViewController:avc animated:true completion:nil];
}
EDIT: I have another view controller; call it X. X's viewDidLoad function has a timer counting down before X dismisses itself and presents another view controller. I noticed an interesting timing issue here: when the notification comes slowly enough so that the UIAlertController appears after X's timer is up and another view controller has been presented, the alertController doesn't dismiss itself. If the opposite happens - the notification comes quickly enough making the UIAlertController appears before X dismisses itself, then the whole AlertController will be flushed when the timer is up (which makes sense, I guess...). How can I prevent this from happening?
You can use perform selector method, like this:
- (void)showNotification:(NSString *)text {
UIAlertController* avc = [UIAlertController alertControllerWithTitle:#"Success" message:text
preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *ok = [UIAlertAction actionWithTitle:#"Ok" style:UIAlertActionStyleCancel handler:nil];
[avc addAction:ok];
[self performSelector:#selector(dissmissAlert:) withObject:avc afterDelay:3.0];
[self.window.rootViewController presentViewController:avc animated:true completion:nil];
}
-(void)dissmissAlert:(UIAlertController *) alert{
[alert dismissViewControllerAnimated:true completion:nil];
}

presentViewController not working in viewDidLoad

In this code the alert action is shown every time the app become active:
- (void)viewDidLoad {
[super viewDidLoad];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(applicationDidBecomeActive:)
name:UIApplicationDidBecomeActiveNotification
object:nil];
}
- (void)applicationDidBecomeActive:(NSNotification *)notification
{
UIAlertController *alertController = [UIAlertController alertControllerWithTitle:#"Please make your choice"
message:#"Would you like a cup of coffee?"
preferredStyle:UIAlertControllerStyleActionSheet];
UIAlertAction *yesAction = [UIAlertAction actionWithTitle:#"YES"
style:UIAlertActionStyleDefault
handler:^(UIAlertAction *action) {
NSLog(#"You tapped YES");
}];
UIAlertAction *maybeAction = [UIAlertAction actionWithTitle:#"MAYBE"
style:UIAlertActionStyleDefault
handler:^(UIAlertAction *action) {
NSLog(#"You tapped MAYBE");
}];
UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:#"Cancel"
style:UIAlertActionStyleCancel
handler:nil];
[alertController addAction:yesAction];
[alertController addAction:maybeAction];
[alertController addAction:cancelAction];
[self presentViewController:alertController animated:YES completion:nil];
}
Also, everything works as expected if I move the code block of the UIAlertController in viewDidAppear method.
But if I move the UIAlertController in viewDidLoad :
- (void)viewDidLoad {
UIAlertController *alertController [...]
[...]
[self presentViewController:alertController animated:YES completion:nil];
}
it doesn't works. The alert is not shown.
In viewDidLoad it is not part of the view hierarchy at that time hence it is silently ignored, on viewWillAppear at this time the view hierarchy is already set up hence the reason it works.

why isn't removeFromSuperview removing my movie subview? Xcode

I'm trying to get a movie that plays to dismiss on its own without having to hit the "Done" button. I think it's a recent iOS 6 problem since I'm following a tutorial exactly and when I insert NSLogs the NSNotification and removeFromSuperview are being recognized but the movie stays there once it has ended. Here's my code, please help:
- (IBAction)playMovie:(id)sender
{
NSURL *url = [NSURL fileURLWithPath:[[NSBundle mainBundle]
pathForResource:#"RomneyFlipSequence1" ofType:#"mov"]];
_moviePlayer =
[[MPMoviePlayerController alloc]
initWithContentURL:url];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(moviePlayBackDidFinish:)
name:MPMoviePlayerPlaybackDidFinishNotification
object:_moviePlayer];
_moviePlayer.controlStyle = MPMovieControlStyleDefault;
_moviePlayer.shouldAutoplay = YES;
[self.view addSubview:_moviePlayer.view];
[_moviePlayer setFullscreen:YES animated:NO];
}
- (void) moviePlayBackDidFinish:(NSNotification*)notification {
MPMoviePlayerController *player = [notification object];
[[NSNotificationCenter defaultCenter] removeObserver:self
name:MPMoviePlayerPlaybackDidFinishNotification
object:player];
if ([player
respondsToSelector:#selector(setFullscreen:animated:)])
{
[player.view removeFromSuperview];
}
}
#end
You entered the player into fullscreen mode.
[_moviePlayer setFullscreen:YES animated:NO];
Reading other solutions in SO it seems that when you press "Done" the player is taken out of fullscreen first, and then the notification is thrown. After reading this answer, adding
[_moviePlayer setFullscreen:NO animated:YES];
before your removeFromSuperview call will solve your problem.
If the above doesn't work, in addition you may try stoping the player first so the full code will be
-(void)removePlayer:(MPMoviePlayerController *)player{
NSLog(#"Playback Finished");
[[NSNotificationCenter defaultCenter] removeObserver:self name:MPMoviePlayerPlaybackDidFinishNotification object:_moviePlayer];
[[NSNotificationCenter defaultCenter] removeObserver:self name:MPMoviePlayerDidExitFullscreenNotification object:_moviePlayer];
[_moviePlayer stop]; // <-- May not be needed
if ([_moviePlayer respondsToSelector:#selector(setFullscreen:animated:)])
{
[_moviePlayer setFullscreen:NO animated:YES];
[_moviePlayer.view removeFromSuperview];
}
_moviePlayer=nil;
}
I use the same method for both notifications "Done" and "PlayBackFinished"
Hope this helps.
You had added _moviePlayer.view as a view and you are trying to remove player.view
i think this will do it :
- (void) moviePlayBackDidFinish:(NSNotification*)notification {
MPMoviePlayerController *player = [notification object];
[[NSNotificationCenter defaultCenter] removeObserver:self
name:MPMoviePlayerPlaybackDidFinishNotification
object:player];
if ([player
respondsToSelector:#selector(setFullscreen:animated:)])
{
[_moviePlayer.view removeFromSuperview];
}
}