如何显示NSMigrationManager在UILabel中的迁移进度? [英] How to show migration progress of NSMigrationManager in a 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屋!