我完全不熟悉iOS中的线程。我有一个基于标签栏的应用程序,其标签如下:
selectedSegmentIndex
[self doLoadData]
我希望在实际调用init
之前先调用tabBarController.selectedSegmentIndex = 1
方法。所以,我在我的applicationDidFinishLaunching
:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
[Constants configureApp];
self.window.rootViewController = self.navigationController;
dispatch_async(dispatch_get_global_queue(0, 0), ^{
[[[[tabBarController viewControllers] objectAtIndex:1] topViewController] init ];
[self.window addSubview:tabBarController.view];
[self.window makeKeyAndVisible];
});
self.window.rootViewController = self.navigationController;
dispatch_async(dispatch_get_global_queue(0, 0), ^{
[[[[tabBarController viewControllers] objectAtIndex:1] topViewController] init ];
[self.window addSubview:tabBarController.view];
[self.window makeKeyAndVisible];
});
这样做的行为就是它确实有用:
请帮助,因为我知道我做错了!
答案 0 :(得分:2)
就像bbum所说,UIKit不是线程安全的。而不是在后台抛出init,问问自己哪个部分使init更慢并且从那里开始工作。
您是从网上加载图片还是解析某些文件?这些是使用Grand Central Dispatch在后台放置的东西的好例子(至少图像的下载部分,显示仍应在主线程中完成)。
不是将整个init包装在一个调度中,而是在视图控制器的init方法中尝试这样的事情:
dispatch_async(queue, ^{
[self doLoadData]
dispatch_async(dispatch_get_main_queue(), ^{
//Set new data to be displayed
});
});
确保在执行此操作时,视图在没有数据的情况下看起来没问题(并且在正常下载后加载数据),因为它会在下载完成之前显示。
答案 1 :(得分:1)
你不能随意向队列发送各种任务,并希望它能够正常工作。
除非将类和/或方法明确记录为线程安全,否则它不是线程安全的。
同样,您必须非常仔细地设计自己的类以保证线程安全。虽然队列使这更容易做到,但它仍然充满锋利的边缘。
在这种情况下,您正在使用主队列中的UIKit对象。这通常是在一些特定情况之外禁止的。
您需要阅读Concurrency Programming Guide了解详情。