我正在一个UI测试框架(KIF-next)上运行,该框架在应用程序的主线程中运行。基本过程是:
runUntilDate:
将主循环旋转0.1秒。 这种方法效果很好。您可以模拟点击事件,可以在滑块之间滑动,观看警报视图的动画效果,scrollToRowAtIndexPath:。除了一种特定的方案(拖动滚动视图)之外,其他所有东西都运行良好。
您可以上下拖动滚动视图,但是松开手指时什么也没有发生。此外,触摸事件将不再被其他视图识别,您所能做的就是拖动滚动视图。
如果此执行模式结束并且代码退出,则滚动视图将进行反弹/减速,但这不是一个选项,因为我正在执行顺序执行的ocunit中工作。
我的问题:为什么会发生这种情况,可以采取什么措施纠正它?
我有两个演示:
演示1:阻止您的整个应用程序
使用此代码,您可以测试应用程序并确认一切正常,直到滚动为止。之后,没有任何效果。
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
double delayInSeconds = 2.0;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
while (YES) {
[[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.25]];
}
});
return YES;
}
演示2:暂时阻止
如果将此代码连接到按钮,则先单击按钮然后滚动,将看到与上述相同的效果。计时器完成后,您将看到您的应用程序恢复活力。
- (IBAction)spinButtonClicked:(id)sender
{
[[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:5]];
}
最佳答案
正如Dave指出的,问题与运行循环模式有关。应用程序将主要驻留在kCFRunLoopDefaultMode
模式下,但是当用户开始滚动时切换为UITrackingRunLoopMode
,然后在滚动视图结束减速后再次返回。这似乎是为了防止正常计时器在滚动过程中触发。 (您可以在Safari中看到此内容,其中在滚动过程中动画停止更新。)
机制似乎如下。
UIApplication
具有堆栈,以跟踪应用程序请求的当前运行循环模式。 GSEventRunModal
,后者又使用应用程序的当前运行模式CFRunLoopRunInMode
来调用kCFRunLoopDefaultMode
。 [[UIApplication sharedApplication] pushRunMode:UITrackingRunLoopMode requester:self]
。 CFRunLoopStop
创建的运行循环上调用GSEventRunModal
。 GSEventRunModal
循环并再次调用CFRunLoopRunInMode
,这次是UITrackingRunLoopMode
。 [[UIApplication sharedApplication] popRunMode:UITrackingRunLoopMode requester:self]
并执行类似的步骤。 我长期运行的函数调用
runUntilDate:
的问题永远不会终止,因此CFRunLoopStop
无效。一种方法是混淆pushRunMode:requester:
和popRunMode:requester:
并用我自己的内部逻辑做类似的事情。由于我将不会收到任何实际的用户交互,因此我实际上采用的方法是将触摸移动事件发送到应用程序,并检查其上有哪些actionRecognizer。如果有一个
UIScrollViewPanGestureRecognizer
进入Began
阶段,则其余的运行循环将通过UITrackingRunLoopMode
完成。触摸模拟完成后,我将继续在该模式下运行,直到scrollView.dragging == NO
为止。您可以在https://github.com/bnickel/KIF/blob/kif-next/Additions/UIView-KIFAdditions.m#L368上看到它的运行情况
关于ios - UIScrollView和-[NSRunLoop runUntilDate:],我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/17375008/