2010-11-20 40 views
5

UIScrollview中的事件跟踪会阻止主线程。我使用主线程来运行驱动某些动画的计时器 - 结果是,任何用户与可滚动视图(向上或向下拖动等)的交互都会导致动画(在主循环中运行)冻结。有没有解决的办法?UIScrollView中的事件跟踪会阻止主线程。任何修复?

我试过RTFM关于NSRunloop(CFRunLoopAddCommonMode等),但它非常简洁,让我相信更好地避免修改事件优先级/线程优先级。任何人有任何见解?

+1

你只能在主线程中做UI的东西 - 所以搞乱线程优先级不适用。我很好奇 - 你知道NSTimers是否停止开火,或者定时器开火,但是拒绝应用你在动画中所做的更改? *动画完成* UIScrollView,或*滚动视图*内*即您是否尝试制作动画并更改scrollview滚动尝试更改的相同内容? (滚动视图Rects等)? – Brad 2010-11-20 01:49:05

+0

谢谢布拉德 - 我希望(可能很危险)做的事情是将EventTracking模式添加到主runloop,从而允许它继续与EventTracking runloop同时运行。被阻止的动画实际上是在与包含scrollview的视图完全不同的视图上完成的。要回答你的其他问题,NSTimer完全停止发射。它似乎完全被更高优先级的跟踪(无关)UIScrollView上的用户事件所阻止。 – 2010-11-20 02:10:15

回答

16

而不是使用的NSTimer的静态构造函数之一,创建定时器对象和手动安排像这样的将是完全不同的,当然,特别是因为它听起来像你”重新使用重复计时器。我想你可以看到基本的想法。

当您滚动时,运行循环进入防止执行“默认模式”任务的模式。静态NSTimer函数全部安排在默认模式下,这就是为什么当你滚动时他们不会触发。手动调度计时器可让您指定模式,而NSRunLoopCommonModes包含滚动所使用的运行模式。

+0

太棒了!我一直在使用:\t [[NSRunLoop mainRunLoop] addTimer:loopTimer forMode:[NSRunLoop currentMode]];仍然被阻止。你的修复工作完美。 – 2010-11-24 14:02:36

+0

谢谢万亿!这种修复极大地增加了我的懒加载表的可用性。 – Nailer 2012-11-30 11:36:41

0

一个想法是让计时器在单独的线程上运行。当计时器触发时,然后在主线程上运行它需要执行的操作。

编辑:

是啊,我完全忘了怎样的UIScrollView块几乎一切。另一个想法(虽然非常难看)是检查定时器是否在UIScrollView的委托方法期间触发(即-scrollviewDidScroll等)。这实际上是一种破解,但它基本上是我知道在滚动期间执行任何代码的唯一方式。

NSTimer *timer = [[NSTimer alloc] initWithFireDate:[NSDate dateWithTimeIntervalSinceNow:delayInSeconds] interval:0 target:yourObject selector:yourSelector userInfo:nil repeats:NO]; 
[[NSRunLoop mainRunLoop] addTimer:timer forMode:NSRunLoopCommonModes]; 
[timer release]; 

你paramters到initWithFireDate:

+0

谢谢,是的,我实际上已经在主线程上运行我的动画定时器。看起来用户事件的幕后跟踪运行的优先级高于主线程,所以当连续的事情(如滚动)发生时,它会阻塞主线程很长一段时间... – 2010-11-20 05:19:56

+0

@Andy Milburn:请参阅编辑另一个想法。 – 2010-11-22 20:52:22