我刚刚阅读了以下帖子并尝试实施那里描述的方法:
那里描述的所有东西都可以正常工作。但!当我运行验收测试时,有一件事会破坏确定性。
这是 Github 上的仓库,该帖子的作者在其中推送了他的实验(可以在页面底部的评论中找到):https ://github.com/moredip/2012-Olympics-iOS--iPad-and -iPhone--source-code/tree/kiwi-acceptance-mk1
考虑一下他用于点击视图的这段代码:
- (void) tapViewViaSelector:(NSString *)viewSelector{
[UIAutomationBridge tapView:[self viewViaSelector:viewSelector]];
sleepFor(0.1); //ugh
}
... wheresleepFor
有以下定义:
#define sleepFor(interval) (CFRunLoopRunInMode(kCFRunLoopDefaultMode, interval, false))
这是一个幼稚的尝试(“幼稚”不是关于作者,而是关于它是第一个进入脑海的事实)等待一小段时间,直到所有动画都被处理并浸泡所有可能的已(或可能)安排到主运行循环的事件(另请参阅此评论)。
问题是这个幼稚的代码不能以一种确定的方式工作。有一堆 UI 交互会导致在当前编辑的文本字段的键盘消失之前按下 fx 下一个按钮,等等......
如果我只是将时间从 0.1 增加到 fx 1,所有问题都会消失,但这会导致每一个交互,比如“用文本填充文本字段......”或“点击带有标题的按钮......”变成成本一个第二!
所以我的意思不仅仅是在这里增加等待时间,而是一种进行这种人为等待的方法来保证我确实可以继续我的测试用例下一步。
我希望它应该是一种更可靠的方法,可以等待足够多的时间,直到当前动作引起的所有内容(所有过渡/动画或任何主运行循环内容)都完成。
总结这一切都是一个问题:
有没有办法耗尽/排出/浸泡所有调度到主线程及其运行循环的东西,以确保主线程空闲并且它的运行循环是“空的”?
这是我最初的解决方案:
// DON'T like it
static inline void runLoopIfNeeded() {
// https://developer.apple.com/library/mac/#documentation/CoreFOundation/Reference/CFRunLoopRef/Reference/reference.html
while (CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.1, YES) == kCFRunLoopRunHandledSource);
// DON'T like it
if (CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.1, YES) == kCFRunLoopRunHandledSource) runLoopIfNeeded();
}