Popover between view controllers and cancel button - uipopovercontroller

I have two tableviews, let´s say one and two, and one presents two when a textfield is tapped, and for this i have:
-(void) setProducts:(UITextField *) box
{
UIViewController *selectInBox = [self.storyboard instantiateViewControllerWithIdentifier:#"selectingProducts"];
popover = [[UIPopoverController alloc] initWithContentViewController:selectInBox];
[popover presentPopoverFromRect:box.bounds inView:box permittedArrowDirections:UIPopoverArrowDirectionUp animated:YES];
}
-(BOOL)textFieldShouldBeginEditing:(UITextField *) textField
{
if (textField.tag == 2)
{
[self setProducts:textField];
}
Everything works great until know, table "two" appears inside the popover and underneath the textfield, but table "two" has a cancel button that it is supposed to dismiss tableview "two"(inside tableview "one"). So i went to my cancel method in tableview "two" and i did this but it isn´t working and i don't think it can be simple has this:
- (IBAction)cancel:(id)sender
{
[self removeFromParentViewController];
}
I also tried:
- (IBAction)cancel:(id)sender
{
one *aux = [[one alloc]init];
[aux.popover dismissPopoverAnimated:YES] //popover is a property of tableview one.
}
also tried: "if self isBeingPresented"...and nothing is working!.
Any ideas? help!
thanks in advance

I've used this quite successfully with "popovers" that are presented as form sheets (modally).
- (IBAction)cancelButtonTapped:(id)sender
{
[self dismissViewControllerAnimated:YES completion:nil];
}
The dismissPopoverAnimated:YES... should be invoked from the presenting view controller.

Related

Xcode: Detecting when a navigation controller implemented "back button" is pressed

Scenario
I have an app with a navigation controller. When the navigation controller pushes another controller onto the stack, in the upper left corner of the screen it shows the back button "<(title of the last view controller)".
What I need
I need something like (pseudo code)...
-(void)detectedBackButtonWasPushed {
NSLog(#"Back Button Pressed");
//Do what I need done
}
Question
Because this button is created by the navigation controller and I did not create this button in storyboards, how do I get the back button 'hooked up' to a method like this?
examples of what Ive tried for Oleg
-(void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated {
UIViewController *vc = [self.storyboard instantiateViewControllerWithIdentifier:#"notification"];
if (viewController == vc) {
NSLog(#"BACK BUTTON PRESSED");
}
}
Is this how I'm supposed to do it? Cause this doesn't work.
Use viewWillDisappear to detect this.
-(void) viewWillDisappear:(BOOL)animated
{
if ([self.navigationController.viewControllers indexOfObject:self]==NSNotFound)
{
[self backButtonPressed];
[self.navigationController popViewControllerAnimated:NO];
}
[super viewWillDisappear:animated];
}
-(void)backButtonPressed
{
NSLog(#"YEA");
}
Previously, I have solved this by setting the navigationBar leftItem to be a back button with a custom selector that dismisses the view along with whatever else it needed to do.
I might also suggest looking at the back button item and adding a target:self that is called on touch.

iOS 7: Keyboard not showing after leaving modal ViewController

I've got a HomeViewController that has different modal segues to several other UIViewControllers. If I try to show the keyboard on a UITextField within the HomeView, everything works fine. However, if I try to show the keyboard on a UITextField (using becomeFirstResponder) after returning from any of the modal View Controllers, the keyboard never shows.
Here's some sample code from one of the setups I've tried:
In HomeViewController:
- (void)viewDidAppear:(BOOL)animated
{
static BOOL firstTimeComplete = false;
if (!firstTimeComplete) {
firstTimeComplete = true;
} else {
UITextField *textField = [[UITextField alloc] init];
[self.view addSubview:textField];
[textField performSelector:#selector(becomeFirstResponder) withObject:nil afterDelay:3]
}
}
In ModalViewController:
- (IBAction)done:(id)sender
{
[self dismissViewControllerAnimated:YES completion:nil];
}
Where done: is linked to the "Done" button via a touch up inside event.
A few things I've tried:
Converting the modal segues to push segues fixes the issue, but I don't want a Nav bar in any of the child views
I've tried disabling and enabling animations when dismissing the
modal view controller (using dismissViewControllerAnimated:)
Using unwind segues in the storyboard rather than doing it programmatically
Anyone have an idea of what may be going on?
After deleting tons of code, I finally found out that a custom NavigationController was being used and this was the root cause:
#implementation MSLNavigationController
- (NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationPortrait;
}
- (BOOL)shouldAutorotate
{
return NO;
}
#end
The app doesn't need this code, so I've nuked the file. (But an explanation as to why this would be hiding the keyboard would be awesome :))
You did not call [super viewDidAppear:animated]
In place like that i have workaround that works pretty well
- (void)viewDidAppear:(BOOL)animated{
[super viewDidAppear:animated];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^
{
if (self.textView.text.isNotEmpty)
{
[self.textView becomeFirstResponder];
}
});
}
I have been struggling with this problem for some time, so I'll post here what I found out.
I was calling textField.becomeFirstResponder() in viewWillAppear but on iOS 7, after the modal was dismissed, the keyboard would not show again, even when you would tap on the textField.
For me calling textField.resignFirstResponder() when the modal is presented, solved the issue. It seems like the input field was already marked as first responder and then would not react to the new calls.

load UIViewController view over singleViewController style app

I have created a single view based application. I was wanting to overlay UIViewControllers as I needed them, for instance like a modal view thing where if some values are populated then load the next view until you do something there and you can come back.
This is the code I have
- (void) viewWillAppear:(BOOL)animated {
NSMutableDictionary *tempPrefs = [prefsController readPrefs];
NSString *tempName = [tempPrefs objectForKey:#"Name"];
NSString *tempProduct = [tempPrefs objectForKey:#"Product"];
// usedbefore so skip first view (first view == login view
if ((tempName.length != 0) && (tempProduct.length != 0)) {
// you have values, enter new room without checking
[self loadGetProListViewController];
}
}
- (void) loadGetProListViewController {
[self dismissViewControllerAnimated:NO completion:nil];
getProListViewController = [[GetProListViewController alloc] initWithNibName:#"GetProListViewController" bundle:nil];
[self presentViewController:getProListViewController animated:YES completion:nil];
}
However once this method has been reached its executed but nothing is happening..
If anyone could tell me how to create modal viewControllers or some description that would be greatly appreciated.
First you should be aware of UIViewController lifecycle to have an idea where you are able to present different UIViewController
Also I guess you have a bit incorrect architecture (maybe I wrong).
Let's imagine you have firstViewController on which -viewDidAppear method you present getProListViewController
Don't you think that presenting intermediate firstViewController is odd?
I'd reather you would move your if clause to level up. F.e:
/ usedbefore so skip first view (first view == login view
if ((tempName.length != 0) && (tempProduct.length != 0)) {
// present your getProListViewController
} else {
// present your "FirstViewController" (login or whatever)
}
And you haven't faced with your issue at the beginning
Try this
[self presentModalViewController: getProListViewController animated:YES];
instead of your presentviewcontroller
[self presentViewController:getProListViewController animated:YES completion:nil];

How do I present a modal view upon an option in UIActionSheet being tapped?

I have my main view controller, and tapping a button brings up an action sheet. I want one of the options tapped there to bring up an action sheet. I can't seem to figure it out, however, despite all my searching.
I have the following code:
- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex {
NSString *buttonTitle = [actionSheet buttonTitleAtIndex:buttonIndex];
if ([buttonTitle isEqualToString:#"Text"]) {
AddTextViewController *addTextViewController = [self.storyboard instantiateViewControllerWithIdentifier:#"addTextViewController"];
}
Now that I instantiated the view controller, I don't know what to do.
Add this line right after you instantiate it.
if ([buttonTitle isEqualToString:#"Text"]) {
AddTextViewController *addTextViewController = [self.storyboard instantiateViewControllerWithIdentifier:#"addTextViewController"];
[self presentViewController:addTextViewController animated:YES completion:nil];
}
Note
You can also create a custom segue in the Storyboard that presents your view, then instead of instantiating and presenting you can just perform your custom segue. Both work the same.
Storyboard Method
First click your segue in Storyboards, then give it an identifier in the info panel.
Then you can replace your code with this and it should trigger the segue from your Storyboard.
if ([buttonTitle isEqualToString:#"Text"]) {
[self performSegueWithIdentifier:#"infoSegue" sender:self];
}

How to switch from one tab to another and back?

I've got a little problem on navigating through my views.
Here is my configuration :
Ive got 1 Tabbar Controller with 2 relationship segues to 2 simple views embedded inside a navigation controller.
Now i want to navigate from view controller 1 to view controller 3 and i also want to show the correct tab selected inside the tabbar. And if i come from view controller 1, i also want that the back button redirects me the the previous tab. I tried something with a segue connected between that views, but if i do so, it just pushes the view controller onto the navigation stack but not changes the tab. So my question now is, what is the best way of managing this Problem
Screenshot:
Here's a way to do it. But I'm posting this really to illustrate why you shouldn't do it.
I'm using VC2's and VC3's view tag property to pass navigation data around, which has the effect of tightly coupling all three objects.
I override back bar button for the VC1->VC3 context. You lose consistency.
VC3->VC2 provides back animation. VC3->VC1 has no animation as it flips from one tab to another. More inconsistency
VC1->VC3, tap Tab Item 2 transitions to VC2. UI confusion.
Anyway if you still want to do this...
.
ViewController1
Has a "jump to VC3" button, wire up to jumpToVC3:
//ViewController1.m
#import "ViewController1.h"
#implementation ViewController1
- (IBAction)jumpToVC3:(id)sender {
NSArray* viewArray = [[[self.tabBarController viewControllers] objectAtIndex:1] viewControllers];
[[[viewArray lastObject] view] setTag:1];
[self.tabBarController setSelectedIndex:1];
}
#end
"jumptToVC3" switches us to tab 2 and sets the frontmost view's view tag property to 1. IF the frontmost view is VC2, this triggers an immediate segue to VC3. If the frontmost view is VC3, this sets up the back button correctly. If other View Controllers get added to this stack, this navigation will break.
ViewController2
Has a "move to VC3" button, wired to a storyboard segue to VC3 "toVC3"
// ViewController2.m
#import "ViewController2.h"
#import "ViewController3.h"
#implementation ViewController2
//we use the view.tag property as a switch:
//0 = do nothing
//1 = segue to VC3
//2 = go to tab 0
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
if (self.view.tag ==1){
[self performSegueWithIdentifier:#"toVC3" sender:self];
} else if (self.view.tag == 2){
[self.tabBarController setSelectedIndex:0];
}
self.view.tag = 0;
}
- (void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if (self.view.tag ==1) {
[[segue.destinationViewController view] setTag:1];
} else {
[[segue.destinationViewController view] setTag:0];
}
self.view.tag = 0;
}
- (void) viewWillDisappear:(BOOL)animated
{
self.view.tag = 0;
}
#end
ViewController3
Overrides the back button if it's view.tag is set to 1. If you want both context's back buttons to be consistent, you will need to override for the default behaviour as well. You will not be able to get a standard back button look for this override behaviour.
// ViewController3.m
#import "ViewController3.h"
#implementation ViewController3
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
if (self.view.tag == 1) {
self.navigationItem.leftBarButtonItem =
[[UIBarButtonItem alloc] initWithTitle:#"0.0"
style:UIBarButtonItemStyleBordered
target:self
action:#selector(goBack:)];
}
self.view.tag = 0;
}
- (IBAction)goBack:(id)sender {
[[[[self.navigationController viewControllers]
objectAtIndex:0] view] setTag:2];
[self.navigationController popToRootViewControllerAnimated:YES];
}
#end

Resources