好的,我使用Xcode 4.5 / iOS 6上的选项卡式应用程序模板测试了以下内容。
创建了一个名为SampleButton的UIButton子类并实现了 以下方法:
- (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];
}
将此SampleButton添加到第一个标签页。
结果:视图切换到第二个选项卡,但在SampleButton中从不调用touchesCancelled和/或touchesEnded。如果在我触摸该按钮时视图发生变化,那么其中一个或那个不应该发射吗?这被证明是一个巨大的问题,因为在我的应用程序中,当按钮关闭时我正在播放声音,如果用户在按下按钮时切换标签,它将永远不会停止播放。看起来像这样在iOS3和iOS4中运行良好。
答案 0 :(得分:1)
对按钮进行子类化似乎很难做到这一点。只需告诉音频播放器停止播放viewDidDisappear:animated:方法,如R.A.建议。
答案 1 :(得分:1)
当一个视图从其窗口中移除时,它似乎与任何与之关联的触摸分离。因此,当触摸最终结束时,系统不会向视图发送touchesEnded:…
或touchesCancelled:…
。
如果您只想在按下按钮时禁用制表符切换,则可以通过为标签栏控制器提供委托并让委托从NO
返回tabBarController:shouldSelectViewController:
来执行此操作。例如,在您的测试应用中,您可以让FirstViewController
使自己成为标签栏控制器的代理:
- (void)viewWillAppear:(BOOL)animated {
self.tabBarController.delegate = self;
}
视图控制器可以允许标签栏控制器仅在未按下按钮时突出显示选项卡(突出显示):
- (BOOL)tabBarController:(UITabBarController *)tabBarController shouldSelectViewController:(UIViewController *)viewController {
return !_button.highlighted;
}
当从窗口中删除按钮时,它会将其highlighted
属性重置为NO
。因此,解决此问题的一种通用方法是使用键值观察(KVO)来监视按钮的状态(而不是依靠按钮向您发送操作)。将自己设置为按钮的highlighted
属性的观察者,如下所示:
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];
}
我在测试中发现,当按钮从窗口移除时,按钮会发送额外的KVO通知,之前将其highlighted
属性重置为NO
。因此,在处理KVO通知时,请检查该值是否已实际更改:
- (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];
}
}
最后,根据按钮的highlighted
属性启动或停止播放:
- (void)updatePlaybackForButtonState {
if (_button.highlighted) {
NSLog(@"start playback");
} else {
NSLog(@"end playback");
}
}
答案 2 :(得分:1)
我通过设置动作的目标而不是使用触摸方法来解决这个问题:
[self addTarget:self action:@selector(handleKeyPressed) forControlEvents:UIControlEventTouchDown];
[self addTarget:self action:@selector(handleKeyReleased) forControlEvents:UIControlEventTouchUpInside];
[self addTarget:self action:@selector(handleKeyReleased) forControlEvents:UIControlEventTouchCancel];
即使视图交换,这些似乎也会被正确触发。