0

我有一个在 3 个文件中实现的页面视图控制器。其中之一,ModelController.m 实现了“generateData”方法,它基本上只是为这个页面视图控制器构建和格式化所有页面。在这个方法中,我做的第一件事是创建一个带有“取消”按钮的进度条弹出窗口。然后,在 while() 循环中,我继续构建页面,同时,每 10 页更新一次进度条,让用户看到应用程序仍在生成输出。

一旦“generateData”方法完成,即构建所有页面(可能有超过 1,000 甚至 10,000 个页面,具体取决于用户输入),它会将“self”返回给 RootViewController.m 中的一个方法,该方法反过来传递生成的数据在 DataViewController.m 中的“dataObject”到“viewWillAppear”,最终向用户显示该对象中的页面。

这一切都很好,除了“取消”按钮。因为“generateData”方法在主线程上运行,所以它阻塞并且“取消”按钮变得完全没有响应。“块”当然是指它占用所有 CPU 周期,不允许执行任何其他操作,生成 10,000 个页面可能需要一分钟以上,所以我真的希望允许用户取消操作。

我尝试为包含取消按钮的进度条弹出窗口创建一个单独的线程,但这不起作用,因为所有 UI 操作都需要在应用程序的主线程上执行。

几乎似乎起作用的是,当我将“generateData”方法放在单独的线程上并将进度条保留在主线程上时。这可以正常工作,只是现在“generateData”被放在另一个线程上以在后台执行并立即返回,因此返回空的“self”或者更确切地说是空的“dataObject”,导致崩溃,因为该对象中没有任何内容显示。

那么如何检查“generateData”线程是否已完成,并且仅在完成后才“返回自我”?我真的不能有一些 BOOL 真/假变量并在循环中执行,因为主线程上的循环将再次阻塞“取消”按钮。

或者,在 iOS 的冗长方法上实现“取消”按钮的正确方法是什么?也许我做错了,但对于我的一生,我找不到正确的食谱。

提前感谢您的帮助,代码相当广泛,这就是我没有包含任何代码的原因,但我希望我的描述能让您对正在发生的事情有一个很好的了解。如果有帮助,我可以提供代码。

4

1 回答 1

1

正确的方法是异步加载数据(在后台线程上)并更新主(UI)线程以更新进度条等...但是您可能不需要进度条,因为您可能可以加载这些页面的速度快于用户翻转它们的速度,因此加载 100 并让用户玩,而您继续加载下一个 99,900... 除了这些可能不是您应该使用的确切数字...

如果您继续使用进度视图和取消按钮,那么您将在用户按下“取消”时取消后台线程,这会响应,因为您的数据生成是在后台线程上...

查看Grand Central DispatchNSInvocationOperations

这是 Ray Wenderlich 的一个很好的教程,可以帮助您入门。

于 2013-04-08T20:24:24.440 回答