3

我的应用程序中有一些长时间运行的启动任务(如从本地数据存储装载Parse对象)。这些任务应该在界面开始出现之前完成。该应用最初是使用故事板创建的,因此在application:didFinishLaunchesWithOptions:方法结束后界面开始自动显示。我无法阻止主线程,因为Parse SDK会在主线程上触发所有回调函数(因此阻塞导致死锁)。我还需要延迟从应用程序返回:didFinishLaunchesWithOptions:完成设置。所以我做的是:应用程序中的长时间运行任务:didFinishLaunchesWithOptions:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 
    // Dispatch long-running tasks 
    dispatch_group_t startup_group = dispatch_group_create(); 
    dispatch_group_async(startup_group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 
     // Perform some long-running setup here 
    }); 
    // Run main run loop until startup tasks finished (is it OK to do so?) 
    while (dispatch_group_wait(startup_group, DISPATCH_TIME_NOW)) 
     [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.1]]; 
    return YES; 
} 

是否正确使用NSRunLoop?有没有什么潜在的警告?你能提出更优雅的(最好是GCD)解决方案吗?

UPDATE:

  1. 加载解析对象从本地数据存储(即从装载SSD微小文件)不只要操作从web装载的东西。延迟几乎没有引人注意,但足以触发warnBlockingOperationOnMainThread,因此UX不是问题。
  2. 真正的问题是由于在正常主循环上旋转另一个主循环而导致的(偶尔)崩溃,有时会导致重新进入代表方法,这显然不是线程安全的。
  3. 启动屏幕的原因介绍是一个明显的解决方案,但我正在寻找一个更简单和优雅的东西。我有一个感觉它存在。
+3

而是延迟'didFinishLaunchingWithOptions的回报:'我想呈现出装载图,告诉什么应用程序在主窗口的前面做的是一个更好的主意用户。 – KudoCC 2015-04-03 09:53:52

+0

旋转运行循环可能存在的问题:http://stackoverflow.com/questions/26371462/weird-crash-when-launching-app-from-notification-center – 2015-04-06 14:09:37

+0

您的解决方案可以在该方法中进行小改动。我想你的加载对象是应用程序中共享状态的一部分。加载操作完成后,您可以简单地添加一个'ready'标志,并将其设置为'true'。应用程序的其他部分可以重复检查此标志(使用NSTimer),也可以使用KVO或通知来获得完成通知。当涉及UI时,试图强制同步操作通常不是一个好主意。 – allprog 2015-04-09 12:25:36

回答

2

虽然这在技术上取决于您的设置正在执行的操作(例如Web服务调用),但应用程序可能永远不会启动或启动时出现意外的结果。

用户友好的方法是将一个“加载”视图控制器添加到您的故事板,这将是您的登陆视图。在向用户提供信息/状态/适当的任何情况下,在此执行长时间运行的设置,然后推动原始视图控制器。

2

恕我直言我觉得这是更好地做你的东西在你的主视图控制器,并展示一些东西给用户像custom spinner这样你可以下载你的数据和用户知道发生了什么

这是一个好主意,需要很长时间才能启动一个空白屏幕的应用程序或只是一个启动屏幕,没有用户的信息。

+1

没有一个给出的答案_really_解决了这个难题,我希望它能解决这个问题,但我承认所有的答案都是有用的,并且或多或少相似,所以我决定把这个奖项颁给最需要它的人。谢谢大家的时间或精力! – 2015-04-10 18:56:59

+0

谢谢! :)我希望你能以最好的方式解决你的问题! – 2015-04-10 22:21:10

+0

@Alexander Vasenin - 良好的呼叫:) – 2015-04-11 23:35:54

2

滞后于didFinishLaunchingWithOptions:的回报实在是一个坏主意。这会给您的应用程序带来不好的印象,也会给您的设计带来不好的印象。

相反,你可以在视图控制器土地,并显示出重叠视图,显示进度活动完成时,你可以解雇 it.This是正确的做法,你在做什么。

这是第三方库的link,可以轻松显示/隐藏叠加视图并在视图上设置一些文本。

你可以找到许多图书馆这样的只是谷歌的iOS HUD .HUD意味着平视显示器,也可以设计自己使用UIAnimation轻松自定义的东西。

一般来说,

我欣赏你写你已经停止电流或使用WhileNSRunloop运行循环的意义上的代码。

也许你可以稍微改变你的代码,并在你的程序的其他地方使用,以停止当前流或runloop并等待一些东西。

NSDate *runloopUntill = [NSDate dateWithTimeIntervalSinceNow:0.1]; 
while (YourBoolFlag && [[NSRunLoop currentRunLoop] runMode: NSDefaultRunLoopMode runloopUntill]) 

下面的Apple文档会给你深刻的见解NSRunloop12

2

这是创意,但一个非常糟糕的主意。你应该让你的用户界面加载失效保护状态 - 换句话说,假设网络不可用/缓慢,并且显示一个视图,如果在渲染之前没有获取数据,它将不会爆炸。然后,您可以安全地将数据加载到后台队列中,并在加载完成后更新视图或转换到以数据为中心的视图。

dispatch_async(dispatch_get_global_queue(QOS_CLASS_USER_INITIATED, 0), ^{ 
     //Load your data here 

     //Dispatch back to the main queue once your data is loaded. 
     dispatch_async(dispatch_get_main_queue(), ^{ 
      //Update your UI here, or transition to the data centric view controller. The data loaded above is available at the time this block runs 
     }); 
    }); 
+0

这可能是一个工作解决方案,但它将背景逻辑耦合到UI,这不是一个好主意恕我直言。 – allprog 2015-04-09 12:28:19

+0

@allprog不确定你的意思,你能详细说明一下吗? – RyanR 2015-04-09 13:07:00

相关问题