0

I have a very basic application in which a second ViewController is instantiated if the conditions of an 'if' statement are true. Upon loading of the second ViewController, the methods of the first ViewController still run. I need all previous methods to stop for the application to run correctly.

// In FirstViewController.h

#import <UIKit/UIKit.h>

@interface FirstViewController : UIViewController
{
    NSTimeInterval beginTouchTime;
    NSTimeInterval endTouchTime;
    NSTimeInterval touchTimeInterval;
}

@property (nonatomic, readonly) NSTimeInterval touchTimeInterval;

- (void) testMethod;

@end

// In FirstViewController.m

#import "FirstViewController.h"
#import "SecondViewController.h"

@implementation FirstViewController

@synthesize touchTimeInterval;

- (void)viewDidLoad
{
    [super viewDidLoad]; 
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
}

- (void) testMethod
{
if (touchTimeInterval >= 3)
{
NSLog(@"Go to VC2");
SecondViewController *secondBViewController = [self.storyboard instantiateViewControllerWithIdentifier:@"SecondViewController"];
             [self presentViewController:secondViewController animated:YES completion:nil];
}
}

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    beginTouchTime = [event timestamp];
    NSLog(@"Touch began");
}

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
    endTouchTime = [event timestamp];
    NSLog(@"Touch ended");

    touchTimeInterval = endTouchTime - beginTouchTime;
    NSLog(@"Time interval: %f", touchTimeInterval);

    [self testMethod]; // EDIT: USED TO BE IN viewDidLoad

}

@end

The second screen successfully loads but the log messages persist, meaning that the methods of FirstViewController still occur, although in the view of the SecondViewController. What am I doing wrong?

ravron
  • 11,014
  • 2
  • 39
  • 66
  • Your first view controller shouldn't be responding to any touches when it's not on screen. Is that what you're saying is happening? – rdelmar Jul 29 '13 at 20:30
  • That is exactly what is happening. I find it so odd and it also makes the application run extremely slow. – user2480376 Jul 30 '13 at 14:21
  • Is this all the code you have? When I try it, it never goes to the second view controller, because testMethod is never called again, and the first time it's called, touchTimeInterval is 0. – rdelmar Jul 30 '13 at 15:06
  • Sorry about that. When I typed the code I didn't have my Xcode project open. I meant to call the method in touchesEnded. Please make this change and see if you get the same problem. Thanks – user2480376 Jul 30 '13 at 15:41

3 Answers3

1

Have a look at - (void)viewWillDisappear:(BOOL)animated and - (void)viewDidDisappear:(BOOL)animated You can implement these methods on your first view controller to stop/disable any activity or touch detection.

picciano
  • 22,341
  • 9
  • 69
  • 82
  • I expected this was the case but I still cannot get it to stop logging the first VC's messages. I never fully understood the two methods you have listed. Is there a generic line of code you can add in both so that all objects/methods will completely stop? – user2480376 Jul 29 '13 at 20:18
1

What you're seeing is the result of the way events are handled in UIKit (check out the "Event Handling Guide for iOS", especially the "Event Delivery: The Responder Chain" section). So what's happening is that since SecondViewController's view doesn't override touchesBegan or touchesEnded, the touch is passed up the responder chain, first to SecondViewController, and then to FirstViewController, which finally does handle those events (FirstViewController is still the window's root view controller after the modal presentation).

Two ways to fix this. You can override touchesBegan and touchesEnded in SecondViewController (or its view I guess), and just have empty methods.

Another way would be to subclass FirstViewController's view, and override the methods there, rather than in the controller. You would still have to do the presentation of SecondViewController from the controller -- you could call a method to do that from the view with [self.nextResponder someMethod].

rdelmar
  • 103,982
  • 12
  • 207
  • 218
  • I tried your first suggestion and it worked. Thanks! However, the second way sounds much cleaner but more confusing. What exactly would I call in someMethod? – user2480376 Jul 30 '13 at 15:52
  • @user2480376, someMethod would just instantiate SecondViewController and present it. In testMethod (now in the view), you would still do the if statement checking if touchTimeInterval >= 3, and if it is, do [self.nextResponder someMethod]. – rdelmar Jul 30 '13 at 15:55
  • When I write the line [self.nextResponder someMethod] in testMethod, I get the error: No visible @interface for 'UIResponder' declares the selector 'someMethod'. Under someMethod I instantiate the SecondVC and present it. What am I missing? – user2480376 Jul 30 '13 at 16:35
  • @user2480376, did you declare someMethod in FirstViewController's .h file? – rdelmar Jul 30 '13 at 17:12
  • @user2480376, oh sorry, you need to cast self.nextResponder: [(FirstViewController *)self.nextResponder someMethod]; – rdelmar Jul 30 '13 at 19:24
  • I received another error. I put that new line of code at the end of the 'if' statement in testMethod and made a second method called someMethod that instantiates and presents the SecondVC. I get the error *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[UIWindow someMethod]: unrecognized selector sent to instance. – user2480376 Jul 30 '13 at 19:37
  • @user2480376, It sounds like the view's nextResponder is the window not FirstViewController. Did you change the class of FirstViewController's view to your subclassed UIView? – rdelmar Jul 30 '13 at 20:08
  • Sorry for the delay. I was out of town. Are you saying to make a custom UIView class and then in the storyboard, change the view's class name to the custom class? – user2480376 Aug 02 '13 at 17:18
  • @user2480376, No, Im saying select the main view of FirstViewController, and change its class from UIView to the custom class where you put the touch handling methods. – rdelmar Aug 02 '13 at 17:24
  • This may sound ignorant but I don't see how that is different from my previous comment. I have only been programming for a little over a month now. – user2480376 Aug 02 '13 at 18:57
  • Am I looking for something like this?: http://stackoverflow.com/questions/11862883/whose-view-is-not-in-the-window-hierarchy – user2480376 Aug 02 '13 at 19:10
  • @user2480376, Maybe they are the same, I think I misread your comment. Have you changed FirstViewController's main view's class to your subclass? Is it working now? – rdelmar Aug 02 '13 at 19:17
0

Is SecondViewController a subclass of FirstViewController? If so the touch events will escalate through the inheritance chain until they are handled. You could override these methods in SecondViewController and have them do nothing (or whatever else you want).

Jordan
  • 4,133
  • 1
  • 27
  • 43
  • SecondVC is not a subclass of FirstVC. I basically have two VC's in my storyboard that have no connections/segues. – user2480376 Jul 30 '13 at 13:59