我目前有一些代码可以执行类似的操作(大大简化,但足以说明这一点):
@property (weak) IBOutlet CustomViewClass *customView;
...
for (int i=0; i<iterations; i++) {
// Crunch some data (Up to ~200,000 operations)...
// Update view to represent where we are in the process:
[_customView setNeedsDisplay:YES];
}
每当我运行代码进行给定的迭代次数时,一旦所有迭代完成,自定义 View 的drawRect:方法只会被调用一次。
我想要的是在每次迭代后强制更新 View ,并等到 View 被重绘后再进入下一次迭代 - 但我在文档中找不到如何让它工作的任何地方如我所愿!
我觉得如果我可以直接调用drawRect:就可以解决我的问题,但我知道NSView不允许这样做!
有人能给我指出正确的方向吗?
最佳答案
缺乏 View 更新甚至不是您当前方法的最大问题。最大的问题是您的应用程序在完成之前一直处于挂起状态。用户无法取消(如果您甚至提供了“取消”按钮)、告诉应用程序隐藏、在工作进行时在应用程序中执行任何其他操作或退出应用程序。
正确的方法是将循环体移至 NSOperation。您可以通过子类化 NSOperation 或使用 block 创建 NSOperation 来完成此操作。然后,将所有操作放入 queue .
如果你在循环中所做的事情可以 safely如果要并行运行,那么您应该创建一个队列并使用该队列。如果您需要一次执行一项操作,请使用依赖项将每个操作链接到其之前的操作。如果它绝对必须发生在主线程上,您可以使用主队列,但您应该在主线程上执行最少的操作,这样您就可以安全地逃脱。
随着工作的进行,在主线程/主队列上运行一些代码,告诉您的 View setNeedsDisplay:
。由于操作不在主队列上(假设您没有将它们放在那里),或者至少被分解,因此在工作正在进行时可能会发生这种情况。
进一步阅读:
- Managing Concurrency with NSOperation (有点旧,正如顶部所承认的,但仍然是一个很好的介绍)
- Concurrency Programming Guide
关于cocoa - 有没有办法让 NSView 重绘更频繁?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13897341/