(This an extension of iOS 7: Keyboard not showing after leaving modal ViewController)
I've got a HomeViewController that uses a NavigationController. Clicking a button takes you to ModalViewController using a modal segue. Pressing the back button then takes you back to the HomeViewController, which then pops up a keyboard. The weird part though is that the keyboard never shows up. I've verified that the UIKeyboardDidShowNotification does get fired , UIKeyboardDidHideNotification doesn't and [textfield isFirstResponder] returns true. Which means the keyboard should be shown right??
I've verified that this only occurs if I have a modal segue, and the NavigationController::shouldAutorotate returns NO.
I've copied the relevant code below. Any help would be greatly appreciated!!
NavigationController.m:
- (BOOL)shouldAutorotate
{
return NO;
}
- (NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationPortrait;
}
HomeViewController.m:
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
if (firstTimeComplete) {
UITextField *textField = [[UITextField alloc] init];
[self.view addSubview:textField];
[textField performSelector:#selector(becomeFirstResponder) withObject:nil afterDelay:3];
}
}
ModalViewController.m:
- (IBAction)back:(id)sender
{
[self dismissViewControllerAnimated:YES completion:nil];
}
Fixed! The problem was because I was using UIInterfaceOrientationPortrait instead of UIInterfaceOrientationMaskPortrait. I think masks are the expected type for supportedInterfaceOrientations
Related
When user tap on textfield so is there any way to open new viewController.
For example, textFieldCountryCode having already value set. now user try to change text at that time new view should be open and after select the option that view should be closed and control comes back to previous viewController with selected value should be set inside textFieldCountryCode.
You should use pickerview to pick value instead of new viewcontroller in this kind of functionality!
You can set pickerview as inputview of your textfield.
Then also if you want to use seperate viewcontroller then in textFieldDidBeginEditing method you can present that viewcontroller and you can use delegate and protocol to set value of textfield which is choosen from viewcontroller!
You can do using passing data using delegate while select country from CountryViecController.
try this code snippet
-(BOOL)textFieldShouldBeginEditing:(UITextField *)textField{
if (textField.tag == 100) {
ViewController *videoVC = [self.storyboard instantiateViewControllerWithIdentifier:#"videoVC"];
videoVC.delegate = self;
[self.navigationController pushViewController:videoVC animated:YES];
return NO;
}
return YES;
}
// delegate method for video controller, here you get selected country
-(void)selectedString:(NSString *)selectedCountry{
NSLog(#"%#",selectedCountry);
}
This kind of functionality can be done by two approach :
First : via pickerview
You need to add your_textfield.inputView = your_pickerview;
and you can done it by handling it by delegate methods of pickerview.
Second : via TextField (Your recommended)
-(BOOL)textFieldShouldBeginEditing:(UITextField *)textField{
if(textField == Your_textfield)
{
Your_viewcontroller *vc= [self.storyboard instantiateViewControllerWithIdentifier:#"Your_viewcontroller_identifier"];
[self.navigationController pushViewController:vc animated:YES];
return NO;
}
return YES;
}
Add the textField and use the following Code:
-(BOOL)textFieldShouldBeginEditing:(UITextField *)textField
{
if ([textField.text isEqualToString:#""])
{
return YES;
}
else
{
NSLog (#"Go To View Controller");
[self changeView];
return NO;
}
}
-(void)changeView
{
secondScreen *obj =[[secondScreen alloc]init];
[self.navigationController pushViewController:obj animated:YES];
}
This code would move you to your second View if the textField already contains text.
In your second view you can define a button like this and set its action to a function as below to return to your previous ViewController
-(void) crossButtonPressed{
[self.navigationController popViewControllerAnimated:YES];
}
I hope this helps you out.
Yes you can push to nextViewController by using textFieldDidBeginEditing method see below code:
- (void)textFieldDidBeginEditing:(UITextField *)textField{
[_myTextfield resignFirstResponder];
TestVc *myVc = [[UIStoryboard storyboardWithName:#"Main" bundle:nil]instantiateViewControllerWithIdentifier:#"TestVc"];
[self.navigationController pushViewController:myVc animated:YES];
}
I have a trio of functions and a property that I use to control my popovers as follows:
-(void)dismissPopoverIfPresentAnimated:(BOOL)animated
{
if (self.currentPopover)
{
[self.currentPopover dismissPopoverAnimated:animated];
self.currentPopover = nil;
}
}
-(void)presentViewController:(UIViewController *)viewController inView:(UIView *)view fromRect:(CGRect)rect suppressArrow:(BOOL)suppressArrow
{
//Did the user just tap on a button to bring up the same controller that's already displayed?
//If so, just dismiss the current controller.
BOOL closeOnly = NO;
if (self.currentPopover)
{
UIViewController *currentController = [self.currentPopover.contentViewController isKindOfClass:UINavigationController.class] ? ((UINavigationController *)self.currentPopover.contentViewController).topViewController : self.currentPopover.contentViewController;
UIViewController *newController = [viewController isKindOfClass:UINavigationController.class] ? ((UINavigationController *)viewController).topViewController : viewController;
if ([currentController isKindOfClass:newController.class])
closeOnly = YES;
[self dismissPopoverIfPresentAnimated:NO];
}
if (!closeOnly)
{
self.currentPopover = [[UIPopoverController alloc] initWithContentViewController:viewController];
self.currentPopover.backgroundColor = [UIColor whiteColor];
[self.currentPopover presentPopoverFromRect:rect inView:view permittedArrowDirections:(suppressArrow ? 0 : UIPopoverArrowDirectionAny) animated:YES];
}
}
(instancetype) initWithContentViewController:(UIViewController )viewController
{
self = [super initWithContentViewController:[[UIViewController alloc] init]];
if (self)
{
UIViewController contentViewController = super.contentViewController;
[contentViewController addChildViewController:viewController];
[viewController didMoveToParentViewController:contentViewController];
[contentViewController.view addSubview:viewController.view];
[self setPopoverContentSize:viewController.preferredContentSize animated:NO];
}
return self;
}
This runs fine in iOS 7, but in iOS 8 the problem is there is a delay between the call to presentPopoverFromRect and when the item actually shows up onscreen. So, if a user double taps a button to show a popover, the first tap will properly dismiss, then "start" the showing of the new controller. The second tap will make the dismiss call (the popover is not yet visible) and then not show the new controller (this is a design feature so that click a button will show a popover, clicking it again will hide it).
The problem is that the call to dismiss the popover doesn't actually work and the popover will show up. At that point I can't get rid of it because my property is nil and I think it is not showing.
My guess is this is an iOS 8 bug where the dismiss somehow doesn't see a visible popover and thus doesn't do anything, where instead, it should prevent it from showing up.
Oh, one last note is that the call to presentViewController is always done on the main thread.
This is the situation...
I have UIViewController, I want to programatically, without any buttons, to go to my Tab Bar Controller or to one of my Table View Controllers.
This is what I did so far:
UIViewController.m
- (void)viewDidLoad
{
[super viewDidLoad];
[self dismissViewControllerAnimated:NO completion:^{
[self performSegueWithIdentifier:#"appLaunched" sender:self];}];
}
This does not work, I made a segue and gave it an id, but the issue remains, my app when launches just shows a white screen and the transition is never made. Can anyone help me please?
Thank you.
Perhaps try something like
- (void)viewDidLoad
{
[super viewDidLoad];
[self pushIt];
}
- (void)pushIt
{
[self.navigationController pushViewController:[self.storyboard instantiateViewControllerWithIdentifier:#"appLaunched"] animated:YES];
}
The problem I am experiencing is that when i try to pop a view controller using the default back swipeGesture in iOS7 viewDidDisappear of the present ViewController does not always get called after viewWillDisappear. I am using the UINavigationController as rootViewController.
App remain struck and does not receive any user inputs after this scenario. Sometimes app gets crashed, when i look at the log: it shows "Can't add self as subview' and in crash log, it showss EXC_BAD_ACCESS. How to fix this, but when i use back button in navigation bar app works normally.
- (void)viewWillDisappear:(BOOL)animated
{
// [self.navigationController.navigationBar setAlpha:1.0f];
[self createBarButtonITems];
self.navigationItem.title = #"Back";
}
- (void)viewDidDisappear:(BOOL)animated
{
[self zoomOutTableWithoutAnimation];
}
-(void)zoomOutTableWithoutAnimation
{
backgroundView.frame = CGRectMake(0,0,320,480);
backgroundView.transform=CGAffineTransformMakeScale(1, 1);
sideMenuTableView.transform=CGAffineTransformMakeScale(0.5,0.5);
sideMenuTableView.frame = CGRectMake(0,150,self.view.frame.size.width/2, self.view.frame.size.height);
sideMenuTableView.hidden = YES;
}
As you mentioned swipe back gesture, this is probably due to the interactive pop back.
As it is mentioned in WWDC 2013, session Custom Transitions Using View Controllers, you cannot assume a viewWillDisappear will be followed by viewDidDisappear. The same goes to viewWillAppear and viewDidAppear.
I'm not sure why you want to call
[self createBarButtonITems]
in viewWillDisappear, did you mean viewWillAppear?
Anyway, it seems to me that [self createBarButtonITems] did some side effect.
Try the following code in viewWillDisappear to undo the side effect:
- (void)viewWillDisappear
{
[self doSomethingHasSideEffect];
id <UIViewControllerTransitionCoordinator> coordinator;
coordinator = [self transitionCoordinator];
if(coordinator && [coordinator initiallyInteractive])
{
[coordinator notifyWhenInteractionEndsUsingBlock:
^(id <UIViewControllerTransitionCoordinatorContext> ctx)
{
if(ctx.isCancelled)
{
[self undoAnySideEffect]
}
}];
}
}
From your code what I can understand is you need a back button with title #"Back" instead of the previous view controllers title
just add this code tho your view controller, in which you trying to do the above stuff view did load method
UIBarButtonItem *backButton = [[UIBarButtonItem alloc] initWithTitle:(IS_IOS_7 ? #"" : #"Back") style:UIBarButtonItemStylePlain target:Nil action:nil];
self..navigationItem.backBarButtonItem = backButton;
Add [super viewWillDisappear:animated];
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
[self createBarButtonITems];
self.navigationItem.title = #"Back";
}
In my app, I press a button and it pulls up a modal presentation sheet (for iPad). Within this modal view I have a scrollview within my main view, and 1 text field within my scroll view.
view controller
view
scrollview
text field
Nothing I have tried resigns the keyboard and I don't know why. The only thing that happens is the blinking cursor in the textfield goes away. My class is the delegate for the scrollview and text fields. Here is what I have tried:
- (void)scrollViewDidScroll:(UIScrollView *)scrollView{
[self.titleTextField resignFirstResponder];
[self.titleTextField endEditing:YES];
[self.view endEditing:YES];
[self.view resignFirstResponder];
[self.scrollView endEditing:YES];
[self.scrollView resignFirstResponder];
}
The method does get called, but the keyboard doesn't go away. Can anyone help me or at least tell me why?
Here is how I present this modalpresentation view:
(it comes from a tableviewcontroller)
didSelectRowAtIndexPath
EditVideo *targetController = [self.storyboard instantiateViewControllerWithIdentifier:#"editVideo"];
targetController.delegate = self;
UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:targetController];
navigationController.modalPresentationStyle = UIModalPresentationFormSheet;
[self presentViewController:navigationController animated:YES completion:nil];
[self.tableView deselectRowAtIndexPath:indexPath animated:YES];
On the iPad for any any non-fullscreen presented ViewController, you must implement -(BOOL)disablesAutomaticKeyboardDismissal to return NO to dismiss the keyboard.
- (BOOL)disablesAutomaticKeyboardDismissal
{
return NO;
}
Once that is implemented, you can call [self.view endEditing:YES];.
Edit:
The other common cause of this problem is returning NO from - (BOOL)textFieldShouldEndEditing:(UITextField *)textField. Implement the method in the UITextFieldDelegate and have it return YES unconditionally to prove that it is not a factor.