Шаблон для загрузки фона iPhone во время init? - PullRequest
1 голос
/ 19 апреля 2010

В настоящее время я запускаю фоновый поток для выполнения некоторых запросов REST в делегате моего приложения didFinishLaunchingWithOptions. Этот поток создает некоторые объекты и заполняет модель, поскольку остальная часть приложения продолжает загружаться (потому что я не блокирую, а didFinishLaunchingWithOptions возвращает YES). Я также установил загрузочный UIViewController «сверху» основного вида, который я разрушил после завершения фоновой инициализации.

Моя проблема заключается в том, что мне нужно уведомить первое представление (назовите его представлением Home), что модель готова и что она должна заполнить себя. Хитрость заключается в том, что фоновая загрузка могла завершиться до вызова Home.viewDidAppear или любого другого метода Home.initX.

Мне трудно все это синхронизировать, и я достаточно долго думал об этом, и мне кажется, что я лаю не на том дереве.

Есть ли здесь какие-то шаблоны для такого рода вещей? Я уверен, что другие приложения начинают с выполнения длительных операций с экранами загрузки:)

Спасибо!

Ответы [ 2 ]

1 голос
/ 20 апреля 2010

Я столкнулся с подобной проблемой некоторое время назад при написании 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);
}

Просто убедитесь, что ваши вызовы потоков в какой-то момент завершили работу с YES.

Это ни в коем случае не шаблон, но я нашел его очень полезным, если вы используете несколько потоков в своем приложении.

1 голос
/ 19 апреля 2010

У меня обычно есть класс 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];
}

Теперь, если создание Фабрики занимает много времени, я просто жду под заставкой или выкладываю другой вид, отображающий счетчик, пока все не будет готово. Я полагаю, вы могли бы использовать эту схему, если вы можете выполнить инициализацию синхронно:

@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];
}

Теперь, когда источник данных завершит загрузку данных, он сообщит экрану заставки, чтобы он воспроизводил реальный контент (в данном случае домашний экран). Это всего лишь грубый набросок (например, в реальном случае управление памятью может отличаться), но в принципе все должно работать нормально.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...