Как показать прогресс миграции NSMigrationManager в UILabel? - PullRequest
1 голос
/ 15 сентября 2011

У меня есть много двоичных данных в Core Data, которые я хотел бы удалить и сохранить в виде файлов, поэтому я настроил код так, чтобы он выполнял миграцию вручную.

Проблема в том, что из-за того, что мне нужно извлечь двоичные данные из Core Data и сохранить их в файлы, процесс миграции может занять очень много времени в зависимости от объема данных.

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

// app did launch
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    ...
    // add the progress label
    self.progressLabel = [[UILabel alloc] initWithFrame:CGRectMake(103, 36, 114, 21)];
    [self.progressLabel setText:@"0%"];
    [self.window addSubview:self.progressLabel];
    [self.window makeKeyAndVisible];
    ...
    // start migration
    [self progressivelyMigrateURL:storeURL];
    ...
}

// manually migrate store
- (BOOL)progressivelyMigrateURL:(NSURL*)sourceStoreURL
{
    NSLog(@"start progressivelyMigrateURL");
    ...
    // create the migration manager
    NSMigrationManager *manager = [[NSMigrationManager alloc] initWithSourceModel:sourceModel destinationModel:targetModel];
    ...
    // register for KVO of migration progress here
    [manager addObserver:self forKeyPath:@"migrationProgress" options:NSKeyValueObservingOptionNew context:NULL];

    // start the migration
    if (![manager migrateStoreFromURL:sourceStoreURL type:type options:nil withMappingModel:mappingModel toDestinationURL:destinationStoreURL destinationType:type destinationOptions:nil error:&error])
    {
        return NO;
    }
    ...
}

// handle KVO of migration process here
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
    if ([keyPath isEqual:@"migrationProgress"])
    {
        float migrationProgress = [[change objectForKey:NSKeyValueChangeNewKey] floatValue];
        int percent = migrationProgress * 100;
        [self.progressLabel setText:[NSString stringWithFormat:@"%d%", percent]];
        [self.progressLabel layoutIfNeeded];
        [self.progressLabel setNeedsDisplay];

        NSLog(@"migrationProgress: %d", percent);
        NSLog(@"self.testLabel text: %@", self.testLabel.text);
    }
}

Миграция выполняется отлично, и я могу подтвердить, что NSLog возвращает увеличивающиеся значения во время миграции.

Проблема в том, что self.progressLabel не перерисовывает каждый раз при обновлении прогресса, а просто пропускает от 0% до 100% во время миграции. Я знаю, что не могу запустить миграцию в отдельном потоке. Как я могу сделать эту работу?

1 Ответ

2 голосов
/ 16 сентября 2011

Вам необходимо выполнить миграцию в фоновом потоке и обновить пользовательский интерфейс при получении уведомлений о ходе выполнения в основном потоке.

- (void)startMigration {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
    NSMigrationManager  * manager = [[NSMigrationManager alloc] initWithSourceModel:sourceModel destinationModel:destinationModel];
    [manager addObserver:self forKeyPath:@"migrationProgress" options:0 context:NULL];
    BOOL success = [manager migrateStoreFromURL:sourceStoreURL type:type options:nil withMappingModel:mappingModel toDestinationURL:destinationStoreURL destinationType:type destinationOptions:nil error:&error];
    [manager removeObserver:self forKeyPath:@"migrationProgress"];
    if(success) {
        dispatch_async(dispatch_get_main_queue(), ^{
        // Go back to the main thread and continue…
        });
    }
}

А при получении уведомлений:

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
    dispatch_sync(dispatch_get_main_queue(), ^{
        CGFloat progress = [(NSMigrationManager *)object migrationProgress];
        // Update UI progress indicator
    });
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...