TouchesEnded and TouchesCancelled are not called

Ok, I tested the following with a tabbed app template on Xcode 4.5 / iOS 6.

  • A tabbed application has been created.
  • A UIButton subclass called SampleButton is created and the following mothods are implemented:

    - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { [super touchesBegan:touches withEvent:event]; } - (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event { [super touchesCancelled:touches withEvent:event]; } - (void) touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event { [super touchesMoved:touches withEvent:event]; } - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { [super touchesEnded:touches withEvent:event]; } 
  • Added this SampleButton to the first tab.

  • Added breakpoints for all sensory methods.
  • Launch on the device.
  • It was tested that all sensory methods work as expected.
  • Now tap SampleButton, and then click the second tab.

RESULT: viewing switches in the second tab, but touching Cutoffs and / or touching Ended are never called in SampleButton. Is it not one or the other of these lights if the view changes while I touch this button? This proves a huge problem, because in my application I play sound until this button works, and it never stops playing if the user switches tabs by clicking on it. This seems to work well in iOS3 and iOS4.

+4
source share
3 answers

I worked on this by setting goals for actions instead of using sensory methods:

 [self addTarget:self action:@selector(handleKeyPressed) forControlEvents:UIControlEventTouchDown]; [self addTarget:self action:@selector(handleKeyReleased) forControlEvents:UIControlEventTouchUpInside]; [self addTarget:self action:@selector(handleKeyReleased) forControlEvents:UIControlEventTouchCancel]; 

They seem to work correctly even when the view is minimized.

+1
source

Subclassing a button seems complicated for this. Just tell the sound player to stop playing in viewDidDisappear: animated: mode, as RA suggested.

+1
source

It seems that when the view is removed from the window, it is separated from any touches associated with it. Therefore, when the contact finally ends, the system does not send touchesEnded:… or touchesCancelled:… to the view.

Workaround by disabling tab switching

If you just want to turn off tab switching when you click a button, you can do this by giving the tab bar controller a delegate and returning the delegate NO from tabBarController:shouldSelectViewController: For example, in your test application, you can FirstViewController delegate the controller of the tab bar:

 - (void)viewWillAppear:(BOOL)animated { self.tabBarController.delegate = self; } 

And the view controller can allow the tab bar controller to select the tab only when the button is not pressed (highlighted):

 - (BOOL)tabBarController:(UITabBarController *)tabBarController shouldSelectViewController:(UIViewController *)viewController { return !_button.highlighted; } 

Workaround when detecting backlight reset button to NO

When a button is removed from the window, it resets the highlighted property to NO . Thus, one common way to get around this problem is to use key value monitoring (KVO) to monitor the state of the button (instead of relying on the button to send you actions). Configure yourself as an observer for the highlighted button property as follows:

 static int kObserveButtonHighlightContext; - (void)viewDidLoad { [super viewDidLoad]; [_button addObserver:self forKeyPath:@"highlighted" options:NSKeyValueObservingOptionOld context:&kObserveButtonHighlightContext]; } - (void)dealloc { [_button removeObserver:self forKeyPath:@"highlighted" context:&kObserveButtonHighlightContext]; } 

During testing, I found that the button sends an extra KVO notification when it is removed from the window before it resets the highlighted property back to NO . Therefore, when processing a KVO notification, make sure that the value has really changed:

 - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { if (context == &kObserveButtonHighlightContext) { if ([change[NSKeyValueChangeOldKey] boolValue] != _button.highlighted) { [self updatePlaybackForButtonState]; } } else { [super observeValueForKeyPath:keyPath ofObject:object change:change context:context]; } } 

Finally, start or stop playback according to the highlighted button property:

 - (void)updatePlaybackForButtonState { if (_button.highlighted) { NSLog(@"start playback"); } else { NSLog(@"end playback"); } } 
+1
source

Source: https://habr.com/ru/post/1445184/


All Articles