我正在开始一个后台线程,在我的app delegate didFinishLaunchingWithOptions
中执行一些REST查询。该线程创建一些对象并在应用程序的其余部分继续加载时填充模型(因为我没有阻止,didFinishLaunchingWithOptions
返回YES
)。我还在主视图的顶部设置了一个加载UIViewController',在后台初始化完成后我将其拆除。
我的问题是我需要通知第一个视图(称之为Home
视图)模型已准备就绪,并且它应该填充自己。诀窍是后台下载可能在调用Home.viewDidAppear
或任何其他Home.initX
方法之前完成。
我很难同步所有这些并且我已经考虑了足够长的时间,感觉我正在咆哮错误的树。
这里有什么模式吗?我确信其他应用程序首先通过加载屏幕执行冗长的操作:)
谢谢!
答案 0 :(得分:1)
我通常有一个Factory类负责将所有对象连接在一起。工厂由applicationDidFinishLaunching:
- (void) applicationDidFinishLaunching: (UIApplication*) app {
// Creates all the objects that are needed to wire
// the application controllers. Can take long. We are
// currently displaying the splash screen, so that we
// can afford to block for a moment.
factory = [[Factory alloc] init];
// Now that we have the building blocks, we can wire
// the home screen and start the application.
home = [[factory wireHomeScreen] retain];
[window addSubview:home.view];
[window makeKeyAndVisible];
}
现在,如果Factory创建需要很长时间,我只需在启动画面下等待,或者放置另一个显示微调器的视图,直到一切准备就绪。如果你可以同步执行初始化,我想你可以使用这个方案:
@implementation Factory
- (id) init {
[super init];
// Takes long, performs the network I/O.
someDataSource = [[DataSource alloc] init…];
return self;
}
- (id) wireHomeScreen {
// Data source already loaded or failed to load.
HomeScreen *home = [[HomeScreen alloc] init…];
[home setDataSource:someDataSource];
return [home autorelease];
}
@end
运气好的话,你的启动例程中只有一个长操作,所以你不会因序列化init而丢失任何东西。
如果您想在后台执行数据源初始化,您可以显示一些介绍屏幕,一旦数据加载就会提示主屏幕:
- (void) applicationDidFinishLaunching: (UIApplication*) app
{
// Create the basic building blocks to wire controllers.
// Will not load the data from network, not yet.
factory = [[Factory alloc] init];
// Display something while the data are being loaded.
IntroScreen *intro = [[IntroScreen alloc] init];
// Main screen, will get displayed once the data are loaded.
home = [[factory wireHomeScreen] retain];
// The intro screen has to know what do display next.
[intro setNextScreen:home];
// Start loading data and then notify the intro screen
// that we are done loading and the show can begin.
[factory.someDataSource startLoadingAndNotify:intro];
[window addSubview:intro.view];
[window makeKeyAndVisible];
}
现在,当数据源已完成加载数据时,它会告诉介绍屏幕提示真实内容(在这种情况下是主屏幕)。这只是一个粗略的草图(例如,在实际情况下内存管理可能会有所不同),但原则上它应该可以正常工作。
答案 1 :(得分:1)
我在回写一个REST应用程序时遇到了类似的问题。它不在主屏幕上,但总的想法是一样的。使用NSURLRequests等同步回调的问题。我发现Apple的一个示例代码并没有真正解决这个问题,而是说明了Apple如何解决它。这是链接...
http://developer.apple.com/iphone/library/samplecode/XMLPerformance/Introduction/Intro.html
他们确实阻止了线程,所以也许这不是你想要的解决方案。简而言之,他们使用......
-(void) get {
finished = NO;
... do threading stuff ...
do {
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
} while (!finished);
}
确保你的线程调用设置在某个时候完成为是。
这不是一种模式,但我发现如果你在应用程序中使用多个线程,它会非常有用。