2011-09-15 6 views
1

私はコアデータのバイナリデータをたくさん持っていますので、手動で移行するようにコードを設定するために、ファイルとして削除して保存したいと思います。UILabelでのNSMigrationManagerの移行の進行状況を表示するにはどうすればよいですか?

コアデータからバイナリを取り出してファイルに保存する必要があるため、データの量によっては移行プロセスに非常に時間がかかることがあります。

ユーザーがアプリがフリーズしているとは思わないように、単純な進捗ラベルを表示したいと思います。

// 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%までスキップされることです。私は別のスレッドで移行を実行できないことを知っています。どうすればこの作品を作れますか?

答えて

2

バックグラウンドスレッドでの移行を正確に実行し、メインスレッドで進捗通知を受け取るとUIを更新する必要があります。

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

が、別のスレッドでコアデータ移行を実行することをお勧めしますか?私はできるだけ避けなければならないと言っている多くの記事を読んだ。 –

+0

コアデータスタックで移行が唯一行われている限り、あなたはかなり安全だと思います。なぜ私はバックグラウンドスレッド上でマイグレーションを実行してはならないのかについての良い議論を見たいと思っています... – Axel

+0

私はそれを試してみます、ありがとう! –

関連する問題