初始化期间iPhone背景加载的模式?

时间:2010-04-19 18:54:17

标签: iphone objective-c multithreading oop initialization

我正在开始一个后台线程,在我的app delegate didFinishLaunchingWithOptions中执行一些REST查询。该线程创建一些对象并在应用程序的其余部分继续加载时填充模型(因为我没有阻止,didFinishLaunchingWithOptions返回YES)。我还在主视图的顶部设置了一个加载UIViewController',在后台初始化完成后我将其拆除。

我的问题是我需要通知第一个视图(称之为Home视图)模型已准备就绪,并且它应该填充自己。诀窍是后台下载可能在调用Home.viewDidAppear或任何其他Home.initX方法之前完成。

我很难同步所有这些并且我已经考虑了足够长的时间,感觉我正在咆哮错误的树。

这里有什么模式吗?我确信其他应用程序首先通过加载屏幕执行冗长的操作:)

谢谢!

2 个答案:

答案 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);
}

确保你的线程调用设置在某个时候完成为是。

这不是一种模式,但我发现如果你在应用程序中使用多个线程,它会非常有用。