popToViewController with interactivePopGestureRecognizer - objective-c

I'm using the following code
[self.navigationController.interactivePopGestureRecognizer addTarget:self action:#selector(handlePopGesture:)];
- (void)handlePopGesture:(UIGestureRecognizer *)gesture {
if (gesture.state == UIGestureRecognizerStateBegan)
{
} else if (gesture.state == UIGestureRecognizerStateEnded) {
NSArray *views = [self.navigationController viewControllers];
[self.navigationController popToViewController:[views objectAtIndex:1] animated:YES];
}
but its not working any ideas how to pop view controller using interactivePopGestureRecognizer?

Make sure that your .h file is the delegate.
#interface YOURVIEWCONTROLLER : UIViewController <UIGestureRecognizerDelegate>
In your .m include
self.navigationController.interactivePopGestureRecognizer.delegate = self;
Then your delegate method should recognize your gestures.

Related

Why is my storyboard not loaded?

I am trying to open a separate storyboard using code for a specific login task.
I created the storyboard and the instance class as follows
+ (instancetype)newStoryboardInstance {
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:NSStringFromClass([self class]) bundle:[NSBundle bundleForClass:[self class]]];
AdyenLoginViewController *viewController = [storyboard instantiateInitialViewController];
return viewController;
}
I am then calling this from another class like this
- (void) viewDidAppear:(BOOL)animated {
if([NWTillHelper isDebug] == 1) {
NSLog(#"%s entered", __PRETTY_FUNCTION__);
}
[AdyenLoginViewController newStoryboardInstance];
}
But the loginController is never shown and no error messages are shown, it just finishes loading my normal storyboard and then stops.
The storyboard name etc is correct as per the class name and no compiler errors or warnings are shown
How can I make it load my specific storyboard?
If you are using navigation controller then viewDidAppear will look like this :-
- (void) viewDidAppear:(BOOL)animated {
if([NWTillHelper isDebug] == 1) {
NSLog(#"%s entered", __PRETTY_FUNCTION__);
}
if([AdyenLoginViewController newStoryboardInstance]) {
[self.navigationContoller pushViewController:[AdyenLoginViewController newStoryboardInstance] animated:true];
}
}
Or you can present the viewController like this :-
- (void) viewDidAppear:(BOOL)animated {
if([NWTillHelper isDebug] == 1) {
NSLog(#"%s entered", __PRETTY_FUNCTION__);
}
if([AdyenLoginViewController newStoryboardInstance]) {
[self presentViewController:[AdyenLoginViewController newStoryboardInstance] animated:true completion:^{
}];
}
}

Why do my touch event not work?

I have declared a void touchesbegan method in my controller but it doesn't work! i don't know why. i have an image view which i plan to click it to move to next controller. so i set the touches began method. i have linked the image view in the xib file but when i click the image. nothing happens. Please help, Thanks.
ViewController.h
#import <UIKit/UIKit.h>
#interface imageViewViewController : UIViewController
{
IBOutlet UIImageView *testing;
}
#property(nonatomic, retain) IBOutlet UIImageView *testing;
#end
ViewController.m
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
if(touch.view == testing)
{
TestViewController *testviewcontroller = [[TestViewController alloc]initWithNibName:nil bundle:nil];
[self.navigationController pushViewController:testviewcontroller animated:YES];
}
}
#end
P.S.
here i tried another method using tap gestures.
testing is the name of my image view. as u can see i comment out the ns log in the imagedidtapped method. it works til that point. however when i tried to navigate it out to another page it fails.
- (void)viewDidLoad
{
UITapGestureRecognizer *tapRecognizer;
[testing setTag:0];
[testing setUserInteractionEnabled:TRUE];
tapRecognizer = [[[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(imageViewDidTapped:)] autorelease];
tapRecognizer.numberOfTapsRequired = 1;
[testing addGestureRecognizer:tapRecognizer];
[self.view addSubview:testing];
[testing release];
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
}
- (void)imageViewDidTapped:(UIGestureRecognizer *)aGesture {
UITapGestureRecognizer *tapGesture = (UITapGestureRecognizer *)aGesture;
UIImageView *tappedImageView = (UIImageView *)[tapGesture view];
switch (tappedImageView.tag) {
case 0:
//NSLog(#"UIImageView 1 was tapped");
[self navigate];
break;
case 1:
NSLog(#"UIImageView 2 was tapped");
break;
default:
break;
}
}
-(void)navigate
{
TestViewController *testviewcontroller = [[TestViewController alloc]initWithNibName:nil bundle:nil];
[self.navigationController pushViewController:testviewcontroller animated:YES];
}
The problem is that by default userInteractionEnabled is NO for a UIImageView so you won't get any touches. Set it to YES.
Also the message handling for touchesBegan is really complicated. You'll be much happier if you attach a UITapGestureRecognizer to the image view.
EDIT: Now you say your touches handling is working, but the navigation is not taking place. So let's concentrate on this part of your code:
-(void)navigate
{
TestViewController *testviewcontroller = [[TestViewController alloc]initWithNibName:nil bundle:nil];
[self.navigationController pushViewController:testviewcontroller animated:YES];
}
Put logging in there to make sure navigate is being called! If it isn't being called, you need to figure out why your other code is not running and calling it. If it is being called, then the problem is probably that self.navigationController is nil, i.e. you are not inside a navigation interface to start with.

How to navigate from UIView to UIViewController

i am aware that uiview does not have navigational control. Thus, i am not able to push from the uiview to the next uiviewcontroller.
here is the code of my method. Please help. Thanks!
- (void)scrollViewDoubleTapped:(UITapGestureRecognizer*)recognizer {
CGPoint pointInView = [recognizer locationInView:self];
NSLog(#"%f , %f",pointInView.x,pointInView.y);
if ((pointInView.x >= (231.0) && pointInView.x <=(293) && pointInView.y >= (193) && pointInView.y <=(218)) )
{
// how to push to next viewcontroller here?
UIView *view = [UIGestureRecognizer view]; //what should i do for this code?
[self viewController];
}
}
-(TestViewViewController*)viewController
{
for (UIView *next = [self superview]; next; next = next.superview)
{
UIResponder *nextResponder = [next nextResponder];
if([nextResponder isKindOfClass:[TestViewViewController class]])
{
return (TestViewViewController*)nextResponder;
}
}
return nil;
}
If you want to get viewcontroller having a view than you can use nextResponder method
So first you get the view from gestureRecognizer:
UIView *view = [gestureRecognizer view];
and than search for the viewcontroller containing the view
Look here
Edit:
if ((pointInView.x >= (231.0) && pointInView.x <=(293) && pointInView.y >= (193) && pointInView.y <=(218)) )
{
// how to push to next viewcontroller here?
UIView *view = [recognizer view]; //what should i do for this code?
UIViewController *viewController = [self getViewControllerFromView:view];
if(viewController) {
// do whatever you want...
UIViewController *newViewController = ...
[viewController.navigationController pushViewController:newViewController animated:YES];
}
}
...
I rewrote method get ViewController to your case. To get it from some view:
-(UIViewController*)getViewControllerFromView:(UIView*) view
{
if([[view nextResponder] isKindOfClass:[UIViewController class]])
{
return (UIViewController*)[view nextResponder];
}
else {
for (UIView *next = [view superview]; next; next = next.superview)
{
UIResponder *nextResponder = [next nextResponder];
if([nextResponder isKindOfClass:[UIViewController class]])
{
return (UIViewController*)nextResponder;
}
}
}
return nil;
}
new edit::
your EAGLView has #property (nonatomic, retain) UIViewController *viewController;
ADD #synthesize viewController = _viewController; to .m file.
CoreMotionAppDelegate::
MainViewController * itemsViewController = [[MainViewController alloc]init];
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:itemsViewController];
glView.viewController = itemsViewController;
[glView startAnimation];
[[self window]setRootViewController:navController];
And than in your scrollViewDoubleTapped method just
EAGLView *v = (EAGLView*)[recognizer view];
UIViewController *viewController = v.viewController;

Working with a container view

This is my situation. I have a viewController. With at the top three buttons and below the buttons a containerview. When you push a button, the container view should change.
This is what I have done in storyboard.
Dragged a view controller into my storyboard. added 3 buttons and a containerview into it.
This view controller is off class viewController
Dragged a second viewcontroller into it. And controlled dragged from the containerView to this view controller. and selected embed segue.
Now in code I do the following for controller viewController
-(IBAction)chooseFirstController:(id)sender {
[self.childViewControllers.lastObject switchToFirst];
}
-(IBAction)chooseSecondController:(id)sender {
[self.childViewControllers.lastObject switchToSecond];
}
-(IBAction)chooseThirdController:(id)sender {
[self.childViewControllers.lastObject switchToThird];
}
And for my containerController.h I do the following.
#interface ContainerViewController : ViewController
#property (nonatomic,strong) FirstController *cont1;
#property (nonatomic,strong) SecondController *cont2;
#property (nonatomic,strong) ThirdController *cont3;
#property (nonatomic,strong) ContainerViewController *currentController;
And in my container.m
- (void)viewDidLoad
{
[super viewDidLoad];
self.cont1 = [[FirstController alloc]initWithNibName:#"FirstController" bundle:nil];
self.cont2 = [[SecondController alloc]initWithNibName:#"SecondController" bundle:nil];
self.cont3 = [[ThirdController alloc]initWithNibName:#"ThirdViewController" bundle:nil];
[self addChildViewController:self.cont1];
self.currentController = self.cont1;
[self.view addSubview:self.cont1.view];
}
-(void)switchToFirst {
if (self.currentController != self.cont1) {
[self addChildViewController:self.cont1];
[self moveToNewController:self.cont1];
}
}
-(void)switchToSecond {
if (self.currentController != self.cont2) {
[self addChildViewController:self.cont2];
[self moveToNewController:self.cont2];
}
}
-(void)switchToThird {
if (self.currentController != self.cont3) {
[self addChildViewController:self.cont3];
[self moveToNewController:self.cont3];
}
}
-(void)moveToNewController:(id) newController {
[self.currentController willMoveToParentViewController:nil];
[self transitionFromViewController:self.currentController toViewController:newController duration:.6 options:UIViewAnimationOptionTransitionFlipFromLeft animations:^{}
completion:^(BOOL finished) {
[self.currentController removeFromParentViewController];
[newController didMoveToParentViewController:self];
self.currentController = newController;
}];
}
But I keep getting error "No known instance method for selector switchtoFirst" in my IBActions.
Can anybody help me?
Thanks in advance.
I would guess that lastObject is returning a UIViewController and doesn't know it's a ContainerViewController - hence doesn't know about the switchtoFirst method.
Try something like:
-(IBAction)chooseFirstController:(id)sender {
UIViewController *vc = self.childViewControllers.lastObject;
if([vc isKindOfClass:[ContainerViewController class]]) {
ContainerViewController *containerVC = (ContainerViewController *)vc;
[containerVC switchtoFirst];
}
}

Using addSubView or presentModalViewController in a standard method with paramaters?

I'm trying to reuse code, I have some tutorial view controllers / views, which I would like to call from an action sheet. However, the calling views are different. Sometimes the tutorial view(s) would need to be added as a subview and sometimes they would be added to the navigation controller.
How can I expand my standard function to cater for these two different situations ?
You can see what I'm having to do instead, which means duplicate code :(
I have a class called which holds the standard code, I want to add calls to views here directly.
-(void)showHelpClickButtonAtIndex:(int)buttonIndex:(UIView *)vw {
if (buttonIndex == CommonUIHelpPagesBtnIdx) {
// do nothing
} else if (buttonIndex == 0) {
NSLog(#"Tutorial here");
}
}
I use in one view like this ...
- (void)actionSheet:(UIActionSheet *)actionSheet
clickedButtonAtIndex:(NSInteger)buttonIndex {
CommonUI *cui = [CommonUI alloc];
[cui showHelpClickButtonAtIndex:buttonIndex:self.view];
[cui release];
if (buttonIndex == CommonUIHelpPagesBtnIdx) {
UIViewController *theController = [[HelpViewController alloc]
initWithNibName:#"HelpView"
bundle:nil onPage:HelpPageCalcBalance];
[self.navigationController.topViewController
presentModalViewController:theController animated:YES];
[theController release];
}
}
And is another view like this...
- (void)actionSheet:(UIActionSheet *)actionSheet
clickedButtonAtIndex:(NSInteger)buttonIndex {
[cui showHelpClickButtonAtIndex:buttonIndex:self.view];
if (buttonIndex == CommonUIHelpPagesBtnIdx) {
theController = [[HelpViewController alloc] initWithNibName:#"HelpView"
bundle:nil onPage:HelpPageGettingStarted];
[self.view addSubview:theController.view];
}
}
Maybe the actionSheets could share one same delegate that would be a root viewController or the appDelegate that would know what to do according to it's current state. Hence the same actionSheet method would be used in both case.
If you put your appDelegate which can always be reached as the actionSheetDelegate, you should be able to gain control on every way to present your view, either modally or not in any of your views + the window.
EDIT (re-Edited with your code): Maybe try this
MyAppDelegate.h:
#interface MyAppAppDelegate : NSObject <UIApplicationDelegate, UIActionSheetDelegate>
(...)
- (void) showHelp;
MyAppDelegate.m:
- (void) showHelp {
UIActionSheet *actionSheet = [[UIActionSheet alloc] initWithTitle:#""
delegate:self
cancelButtonTitle:#"Cancel"
destructiveButtonTitle:nil
otherButtonTitles: #"Tutorial", #"Help Pages", nil];
actionSheet.actionSheetStyle = UIActionSheetStyleBlackOpaque;
[actionSheet showInView:window];
[actionSheet release];
}
- (void)actionSheet:(UIActionSheet *)actionSheet
clickedButtonAtIndex:(NSInteger)buttonIndex {
if (buttonIndex == CommonUIHelpPagesBtnIdx) {
UIViewController *theController = [HelpViewController alloc];
if ([[self lvc] superview] != nil) {
theController = [initWithNibName:#"HelpView"
bundle:nil
onPage:HelpPageGettingStarted];
[window addSubview:theController.view];
} else {
theController = [initWithNibName:#"HelpView"
bundle:nil
onPage:HelpPageCalcBalance];
UINavigationController * navController = [tabBarController selectedViewController];
[navController.topViewController presentModalViewController:theController animated:YES];
}
[theController release];
}
}
and in your viewControllers:
- (void)viewDidLoad {
[super viewDidLoad];
MyAppDelegate *delegate = (MyAppDelegate *) [[UIApplication sharedApplication] delegate];
UIButton *infoButton = [UIButton buttonWithType:UIButtonTypeInfoLight];
[infoButton addTarget:delegate
action:#selector(showHelp)
forControlEvents:UIControlEventTouchUpInside];
UIBarButtonItem *infoItem = [[UIBarButtonItem alloc] initWithCustomView:infoButton];
self.navigationItem.rightBarButtonItem = infoItem;
[infoItem release];
}
Didn't try it but it should work.