如何显示NSMigrationManager在UILabel中的迁移进度? [英] How to show migration progress of NSMigrationManager in a UILabel?

查看:184
本文介绍了如何显示NSMigrationManager在UILabel中的迁移进度?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有很多二进制数据Core数据,我想删除和保存为文件,所以我设置代码,以便它将运行手动迁移。

I have a lot of binary data on Core Data which I would like to remove and save as files so I setup the code so that it would run a manual migration.

问题是,因为我必须从Core Data中提取二进制文件并将其保存到文件,迁移过程可能需要很长时间,具体取决于有多少数据。

The problem is that because I have to pull binary from Core Data and save them to files, the migration process could take a very long time depending on how much data there is.

我想显示一个简单的进度标签,以便用户不会认为应用程序已冻结。

I would like to show a simple progress label so that users wouldn't think that the app is frozen.

// 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

The migration runs perfectly and I can confirm that the NSLog is returning incrementing values while the migration is taking place.

问题是self.progressLabel不会在每次进度更新时重绘,只是从0%跳到100 %,而迁移正在进行。我知道我不能在单独的线程上运行迁移。

The problem is that self.progressLabel does not redraw every time the progress is updated and just skips from 0% to 100% while the migration is taking place. I know I can't run the migration on a separate thread. How can I make this work?

推荐答案

您确实需要在后台线程上执行迁移,

You precisely need to perform the migration on a background thread, and update the UI as you get progress notifications on the main thread.

- (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
    });
}

这篇关于如何显示NSMigrationManager在UILabel中的迁移进度?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆