I'm displaying a popover in iPad with a UINavigation bar. On the second view, I have a UISearchController that can display a keyboard. The keyboard pushes the popover up, which is fine, however if I now push the 'back' button on the UINavigation bar it dismisses the keyboard which is fine, but the popover doesn't slide back down to its original position. Anyone know how to fix that? Thanks!
Ok so I actually figured out (I believe) what your question was asking...and just in case anyone stumbles upon this from google, I figured I'd answer how I did it. It feels like a hack job but I haven't been able to find any other way to do it.
In the controller that brings up the keyboard,I had it post a notification whenever the keyboard dismisses:
[aTextField resignFirstResponder];
[[NSNotificationCenter defaultCenter] postNotificationName:#"movePopups" object:nil];
Then back on my home screen controller, that controls the UIPopover, I added a listener:
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(movePopUpToRightLocation)
name:#"movePopups"
object:nil];
inside the init. Be sure to remember to remove the listener in your dealloc for good programming practice:
[[NSNotificationCenter defaultCenter] removeObserver:self];
So then whenever I get notification that the keyboard disappears, I get a reference to the button that the popover shows up from, and just have it re-appear directly from it:
-(void)movePopUpToRightLocation {
NSLog(#"move pop up to right location");
if (morePopUp) {
UIBarButtonItem *barButtonItem = (UIBarButtonItem *)[[bottomToolBar items] objectAtIndex:0];
[morePopUp presentPopoverFromBarButtonItem:barButtonItem
permittedArrowDirections:UIPopoverArrowDirectionDown
animated:YES];
}
}
I haven't added any checks for which popup it is, but I can easily do that if I have more than 1 type of popover / button that it would appear from. But that's the basic premise that you can go from.
Hope it helps!
You could also register for the UIKeyboardDidHideNotification somewhere in the initializer.
[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(movePopoverBack:) name:UIKeyboardDidHideNotification object:nil];
This code moves the popover back:
- (void)movePopoverBack:(id)sender {
if ([self.settingsPopoverController isPopoverVisible]) {
[self performSelector:#selector(hidePopover) withObject:nil afterDelay:0.1];
[self performSelector:#selector(movePopoverBack) withObject:nil afterDelay:0.5];
}
}
- (void)hidePopover {
[self.settingsPopoverController dismissPopoverAnimated:YES];
}
- (void)movePopoverBack {
[self.settingsPopoverController
presentPopoverFromBarButtonItem:self.bottomToolbar.settingsButton
permittedArrowDirections:UIPopoverArrowDirectionDown
animated:YES];
}
I didn't get it working without the delays, but this seems to be acceptable for my current project. Hope it helps someone.
After you press the Back button you should manually call resignFirstResponder for the search field (for example inside viewDidDisappear).
This should help, but the issue still will be reproduced under iOS 4 when the device is in Landscape orientation with Hthe ome button on the left side
Related
Scenario:
I need to show 3 or more popups one after the other on button click in each popup. I have created a different viewcontroller and xib files for each popup. So for displaying each popup I have used presentViewController instead of pushViewController.
That is, I have used this:
[self presentPopupViewController:searchPopUpView animationType:0];
instead of
[self.navigationController pushViewController:searchPopUpView animated:YES];
For dismissing a popup, the following code has been written:
[self dismissPopupViewControllerWithanimationType:0];
Issue:
The popups are displaying perfectly, but the background gets darker and darker whenever a popup shows up. After all popups have been dismissed I have to finally click on the blank screen to remove those darker parts. How to overcome this issue?
I think you are using MJPopupViewController to show pop-up.
If it is so, Then try this.
Suppose there is a controllerA from which you want to show a pop-up controller popupControllerB.
Then in your controllerA add Notifications Observer
Code to write in controllerA :
// Add Notification Observer when your view initialise.
[[NSNotificationCenter defaultCenter]addObserver:self selector:#selector(dismissPopup) name:#"DISMISS_POPUP" object:nil];
In viewWillDisappear remove the notifications observer
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
This method will be called when you Post-notification from your popupControllerB
-(void)dismissPopup {
[self dismissPopupViewControllerWithanimationType:MJPopupViewAnimationFade];
}
And In popupControllerB, Where you want to dismiss the Pop-up, write this code.
[[NSNotificationCenter defaultCenter] postNotificationName:#"DISMISS_POPUP" object:nil];
Above line of code will call a method written in your controllerA and dismiss the pop-up properly.
If you want to dismiss presented UIViewControllers you can use this code. I have used this approach to dismiss presentedViewControllers. It will dismiss all your presentedViewControllers on your rootViewController.
UIViewController* presVC = self.window.rootViewController;
while (presVC) {
UIViewController* temp = vc.presentingViewController;
if (!temp.presentedViewController) {
[vc dismissViewControllerAnimated:NO completion:^{}];
break;
}
vc = temp;
}
I want to show the screen from Top To Bottom but When I use HCYouTubeParser In my app, when i click on Done Button then screen move from bottom to top.I can not find the coding of Done Button How can it is possible?
HCYouTubeParser, this library using default MPMoviePlayerController class of MediaPlayer Framework which is provided by apple.
see this is the code inside HCYouTubeParser->ViewController.m
- (void)playVideo:(id)sender {
if (_urlToLoad) {
MPMoviePlayerViewController *mp = [[MPMoviePlayerViewController alloc] initWithContentURL:_urlToLoad];
[self presentViewController:mp animated:YES completion:NULL];
}
}
So "Done" button is part of that controller. You have to override that "Done" button functionality by adding observer.
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(doneButtonClick:)
name:MPMoviePlayerWillExitFullscreenNotification
object:nil];
-(void)doneButtonClick:(NSNotification*)aNotification{
NSNumber *reason = [notification.userInfo objectForKey:MPMoviePlayerPlaybackDidFinishReasonUserInfoKey];
if ([reason intValue] == MPMovieFinishReasonUserExited) {
// Your done button action here
}
}
Refer this link :Done button event MPMoviePlayerController
First of all, the library you are using is presenting the view controller and by "default" iOS will do presenting from bottom to top. And you cannot find the code which makes the bottom to top.
Second if you want to change this bottom to top you can do the following to change it.
Make a custom transaction
Add the view controller as a child view controller and animate it from top to bottom or any other way you like.
We are observing unusual behaviour with respect to Keyboard willshow & will hide notification on iOS 8.3.
The viewcontroler (listenig to keyboard notifications) has a textfiled and upon clicking and upon tapping the submit button, the method first resigns the first responder from textfield, and shows an alert to inform warning. Everything works fine, it dismisses the keyboard and shows up the alert as expected. (calls the UIKeyboardWillHideNotification method too).
However, on 8.3, after tapping OK/Cancel on Alertview delegate, it dismisses the alert and it calls up UIKeyboardWillShowNotification & UIKeyboardWillHideNotification respectively, though it was not supposed to be called! This was not expected, as the keyboard was already dismissed before dispalying the alert!
Here is the code snippet, that we are trying:
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
}
- (IBAction)ShowAlert:(id)sender {
[self.TxtField resignFirstResponder];
//This woudln't make any diff either :(
[self.view endEditing:YES];
[self ShowAlertForTest];
}
-(void)ShowAlertForTest{
UIAlertView *theAlertView= [[UIAlertView alloc]initWithTitle:#"Title"
message:#"msg"
delegate:self
cancelButtonTitle:#"Cancel"
otherButtonTitles:#"Yes", nil];
[theAlertView show];
}
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
NSLog(#"buttonIndex = %ld",buttonIndex);
}
- (void)keyboardWillShow:(NSNotification *)aNotification
{
NSLog(#"keyboardWillShow");
}
- (void)keyboardWillHide:(NSNotification *)aNotification
{
NSLog(#"keyboardWillHide");
}
This behaviour is causing issues in our app, when there are cascading alerts triggered from the previous alertview'd delegate - bringing up the keyboard in unneeded situations.
Any help /advice is greatly appreciated!
In our case the keyboard was hidden manually by the app (e.g. when user taps Log In, we hide keyboard and call the server login API). Upon failure the app presents UIAlertView with an error message. When user closes the alert, iOS posts will/did hide & will/did show notifications. Of course the keyboard is not shown & hidden during this sequence, because it is already hidden by the app.
However, we noticed that not hiding keyboard manually, but instead letting iOS to do it for us, fixes the issue. So, the keyboard is hidden automatically in two cases:
when UIAlertView is shown
when view controller is deallocated
Note: the keyboard is automatically shown when UIAlertView is dismissed.
My team did a work around by merely unsubscribing from the keyboard notifications before presenting the alert view and resubscribed to those notifications after the alert view had been dismissed. Not ideal but it resolved the issue for us.
In my case user clicks the login button, then I call;
[self.view endEditing: YES];
//server request here and in completion/fail alert.
Keyboard was closed, alertview is shown nicely, but on cancel/apply click keyboard was shown again and disappeared.But the problem was this was happening sometimes, if server request takes time problem is not seen, if Alertview is shown immediately problem still there. So I decided to call my alerts with delay. Putting delay on alert is solved my problem. Hope this helps.
I just fixed a similar issue. The keyboard keep popup after the alert dismisses It seems like a bug of apple.
I recommand you to use UIAlertController instead of UIAlertView. It will avoid a lot of potential issues
There is a simple solution: If you are using UIAlertController, you can just set the animated to NO
[self presentViewController:alert animated:NO completion:nil];
Let me know if it fixed your problem
I have this problem that has popped up out of the blue, I have checked all of the changes I have made in the past week and nothing seems to explain why my viewDidAppear only gets called when pushing to my VC under certain circumstances. These are the two ways I push to my VC.
-(void)receiveOnHostRoomConnectNotification:(NSNotification *)notificaiton
{
[[NSNotificationCenter defaultCenter]removeObserver:self name:kInitialize object:nil];
[[NSNotificationCenter defaultCenter]removeObserver:self name:kOnHostRoomConnect object:nil];
[[NSNotificationCenter defaultCenter]removeObserver:self name:kOnConnect object:nil];
dispatch_async(dispatch_get_main_queue(), ^{
[self performSegueWithIdentifier:#"toSetListRoomVC" sender:self];
});
}
Upon getting this 'onHost' notification I perform the segue. Pushing to the VC like this works EVERY TIME. viewDidAppear gets called in SetListRoomVC ever time.
However, when pushing upon this notification. the destinationVC's viewDidAppear will NEVER get fired.I havnt made any changes to these methods in a while and I doubt it has to do with them, but just giving explanation as to what is happening.
-(void)receiveInitializeNotification:(NSNotification *)notificaiton
{
[[NSNotificationCenter defaultCenter]removeObserver:self name:kInitialize object:nil];
[[NSNotificationCenter defaultCenter]removeObserver:self name:kOnHostRoomConnect object:nil];
[[NSNotificationCenter defaultCenter]removeObserver:self name:kOnConnect object:nil];
if (self.joinLabelSelected) {
self.roomCodeTextField.inputAccessoryView.hidden = YES;
[self.roomCodeTextField resignFirstResponder];
self.menuView.hidden = YES;
[self returnJoinLabel];
[UIView animateWithDuration:.25 animations:^{
self.roomCodeView.alpha = 0;
self.blurEffectView.alpha = 0;
} completion:^(BOOL finished) {
dispatch_async(dispatch_get_main_queue(), ^{
[self performSegueWithIdentifier:#"toSetListRoomVC" sender:self];
});
}];
}
}
I am also using a custom segue and a embedded navigation controller. This is how I have my custom segue set up.
#implementation CustomSegue
-(void) perform{
[[[self sourceViewController] navigationController] pushViewController:[self destinationViewController] animated:NO];
}
#end
All of my viewDidLoad,viewWillAppear,viewDidAppear implement [super view...:animated];
again, I haven't made any significant changes to any of my load,appear, methods in a while. I really don't understand why this is happening now.
Can anyone give an explanation for this? Also, every once in a while, maybe 10% of the time, the viewDidAppear method will get fired upon pushing the 'onHost' notification.
Thanks for any help. This boggling my mind.
EDIT: I rolled back to a commit from a few days ago and began rebuilding my project. So far viewDidAppear is working. I'll try to pinpoint what exactly is screwing everything up. Very strange though since most of what I have to rebuild is just Helper methods and minor UI updates.
These methods should be invoked every time and I've never seen them not being called.
Maybe you are using multiple subclasses inheriting from UIViewController and forgot to invoke super? In this case the super implementation is indeed not called:
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
// do your stuff
}
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
// do your stuff
}
- (void)viewWillDisappear:(BOOL)animated {
// do your stuff
[super viewWillDisappear:animated];
}
- (void)viewDidDisappear:(BOOL)animated {
// do your stuff
[super viewDidDisappear:animated];
}
There might be some rare cases with interactive UINavigationController transitions, where a -viewWillDisappear: might get called, but no -viewDidDisappear:. E.g. if the user wipes from the left of the screen to navigate back and then cancels this action. This could result in a -viewWillDisappear:, but no corresponding -viewDidDisappear:.
Is your navigation controller ever behind anything? For example I think if you used presentViewController: to display a modal view controller on top of your navigation controller, and then pushed your VC onto the navigation controller, viewDidAppear wouldn't get called since iOS would think it was offscreen.
Have you tried putting NSLogs your navigation controller's viewWillAppear and viewWillDisappear methods to make sure that the navigation controller thinks it is visible when you push your new view controller?
I have a view controller whose view is setup in such a way that it has 3 buttons and other subviews. On clicking one of the buttons(3rd button), i am adding another view controller's view as subview to self.view (in this view i have a search display controller in the active state with keyboard)
I'm able to achieve this using the following code
[self.searchDisplayController setActive:YES];
[self.searchDisplayController.searchBar setShowsCancelButton:NO];
[self.searchDisplayController.searchBar becomeFirstResponder];
Now when i press the 2nd button, i try removing this view from the superview and also try to resign the keyboard in the viewWillDisappear ([self.view endEditing:YES]) in the following manner, but keyboard still doesnt resign
One small edit, it is resigning in case i comment out the following piece of code
- (BOOL)searchBarShouldEndEditing:(UISearchBar *)searchBar {
if (self.dataSource.count)
return YES;
return NO;
}
Try to resign UISearchBar in viewWillDisappear
[yourSearchBar resignFirstResponder];
Inside the method that is called to your 2nd button, just type in
[self.searchDisplayController.searchBar resignFirstResponder];
Leave the viewWillDisappear alone. That is for when the view is done with whatever animation it is doing, and when the view is leaving. If you set the display controller to resigning the responder, it should make it go away immediately.
Hope this helps!
you can do it using NSNotificationCenter as below.
//.m file:
[[NSNotificationCenter defaultCenter]addObserver:self
selector:#selector(ResignFirstResponder:) name:#"resign" object:nil];
in ResignFirstResponder:
[searchBar resignFirstResponder];
in which class you use above addObserver, you have to implement that method.
//.m file from where you want to send action, call method as below. [on your second button click]
[[NSNotificationCenter defaultCenter] postNotificationName:#"resign"
object:nil];