0

人々のデータが複数のデバイスからアクセスできるように、Core Data を iCloud と連携させることを検討してきました。私はこのチュートリアル (http://timroadley.com/) に従って、アプリを最大限に活用してきましたが、いくつかの問題に遭遇しました。

問題 1: アプリを (中断しただけでなく) 閉じて再度開いたときに、テーブルに何も表示されないため、以前のデータが読み込まれていないように見える

問題 2: iCloud なのかアプリなのかわかりませんが、変更を同期するのに時間がかかります。1 つのデバイスで変更を加えると、別のデバイスに表示されるまでに 2 ~ 3 分かかります

誰でも私がこれら2つの問題を解決するのを手伝ってくれますか

このコードは私のAppDelegateにあります

- (void)saveContext
{
    NSError *error = nil;
    NSManagedObjectContext *managedObjectContext = self.managedObjectContext;
    if (managedObjectContext != nil) {
        if ([managedObjectContext hasChanges] && ![managedObjectContext save:&error]) {
             // Replace this implementation with code to handle the error appropriately.
             // abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development. 
            NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
            abort();
        } 
    }
}

- (NSPersistentStoreCoordinator *)persistentStoreCoordinator
    {
    if((__persistentStoreCoordinator != nil)) {
        return __persistentStoreCoordinator;
    }

    __persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel: [self managedObjectModel]];
    NSPersistentStoreCoordinator *psc = __persistentStoreCoordinator;

    // Set up iCloud in another thread:

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

        // ** Note: if you adapt this code for your own use, you MUST change this variable:
        NSString *iCloudEnabledAppID = @"MF4HVVX5DS.Desbrina.Medicine-Tracker";

        // ** Note: if you adapt this code for your own use, you should change this variable:
        NSString *dataFileName = @"Medicine-Tracker.sqlite";

        // ** Note: For basic usage you shouldn't need to change anything else

        NSString *iCloudDataDirectoryName = @"Data.nosync";
        NSString *iCloudLogsDirectoryName = @"Logs";
        NSFileManager *fileManager = [NSFileManager defaultManager];
        NSURL *localStore = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:dataFileName];
        NSURL *iCloud = [fileManager URLForUbiquityContainerIdentifier:nil];

        if (iCloud) {

            NSLog(@"iCloud is working");

            NSURL *iCloudLogsPath = [NSURL fileURLWithPath:[[iCloud path] stringByAppendingPathComponent:iCloudLogsDirectoryName]];

            NSLog(@"iCloudEnabledAppID = %@",iCloudEnabledAppID);
            NSLog(@"dataFileName = %@", dataFileName);
            NSLog(@"iCloudDataDirectoryName = %@", iCloudDataDirectoryName);
            NSLog(@"iCloudLogsDirectoryName = %@", iCloudLogsDirectoryName);
            NSLog(@"iCloud = %@", iCloud);
            NSLog(@"iCloudLogsPath = %@", iCloudLogsPath);

            if([fileManager fileExistsAtPath:[[iCloud path] stringByAppendingPathComponent:iCloudDataDirectoryName]] == NO) {
                NSError *fileSystemError;
                [fileManager createDirectoryAtPath:[[iCloud path] stringByAppendingPathComponent:iCloudDataDirectoryName]
                       withIntermediateDirectories:YES
                                        attributes:nil
                                             error:&fileSystemError];
                if(fileSystemError != nil) {
                    NSLog(@"Error creating database directory %@", fileSystemError);
                }
            }

            NSString *iCloudData = [[[iCloud path]
                                     stringByAppendingPathComponent:iCloudDataDirectoryName]
                                    stringByAppendingPathComponent:dataFileName];

            NSLog(@"iCloudData = %@", iCloudData);

            NSMutableDictionary *options = [NSMutableDictionary dictionary];
            [options setObject:[NSNumber numberWithBool:YES] forKey:NSMigratePersistentStoresAutomaticallyOption];
            [options setObject:[NSNumber numberWithBool:YES] forKey:NSInferMappingModelAutomaticallyOption];
            [options setObject:iCloudEnabledAppID            forKey:NSPersistentStoreUbiquitousContentNameKey];
            [options setObject:iCloudLogsPath                forKey:NSPersistentStoreUbiquitousContentURLKey];

            [psc lock];

            [psc addPersistentStoreWithType:NSSQLiteStoreType
                              configuration:nil
                                        URL:[NSURL fileURLWithPath:iCloudData]
                                    options:options
                                      error:nil];

            [psc unlock];
        }
        else {
            NSLog(@"iCloud is NOT working - using a local store");
            NSMutableDictionary *options = [NSMutableDictionary dictionary];
            [options setObject:[NSNumber numberWithBool:YES] forKey:NSMigratePersistentStoresAutomaticallyOption];
            [options setObject:[NSNumber numberWithBool:YES] forKey:NSInferMappingModelAutomaticallyOption];

            [psc lock];

            [psc addPersistentStoreWithType:NSSQLiteStoreType
                              configuration:nil
                                        URL:localStore
                                    options:options
                                      error:nil];
            [psc unlock];

        }

        dispatch_async(dispatch_get_main_queue(), ^{
            [[NSNotificationCenter defaultCenter] postNotificationName:@"SomethingChanged" object:self userInfo:nil];
        });
    });

    return __persistentStoreCoordinator;
}

- (NSManagedObjectContext *)managedObjectContext {

    if (__managedObjectContext != nil) {
        return __managedObjectContext;
    }

    NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];

    if (coordinator != nil) {
        NSManagedObjectContext* moc = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];

        [moc performBlockAndWait:^{
            [moc setPersistentStoreCoordinator: coordinator];
            [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(mergeChangesFrom_iCloud:) name:NSPersistentStoreDidImportUbiquitousContentChangesNotification object:coordinator];
        }];
        __managedObjectContext = moc;
    }

    return __managedObjectContext;
}

- (void)mergeChangesFrom_iCloud:(NSNotification *)notification {

    NSLog(@"Merging in changes from iCloud...");

    NSManagedObjectContext* moc = [self managedObjectContext];

    [moc performBlock:^{

        [moc mergeChangesFromContextDidSaveNotification:notification];

        NSNotification* refreshNotification = [NSNotification notificationWithName:@"SomethingChanged"
                                                                            object:self
                                                                          userInfo:[notification userInfo]];

        [[NSNotificationCenter defaultCenter] postNotification:refreshNotification];
    }];
}

これはマスタービューコントローラーにあります

- (void)reloadFetchedResults:(NSNotification*)note {
    NSLog(@"Underlying data changed ... refreshing!");
    [self fetchedResultsController];
    NSLog(@"%@", note.object);
}

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    self.navigationItem.leftBarButtonItem = self.editButtonItem;

    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(reloadFetchedResults:)
                                                 name:@"SomethingChanged"
                                               object:[[UIApplication sharedApplication] delegate]];
}

- (void)viewDidUnload
{
    [super viewDidUnload];
    // Release any retained subviews of the main view.

    [[NSNotificationCenter defaultCenter] removeObserver:self];
}
4

2 に答える 2

1

問題 1: アプリを (中断しただけでなく) 閉じて再度開いたときに、テーブルに何も表示されないため、以前のデータが読み込まれていないように見える

すべてのデータを管理オブジェクト コンテキストに保存していることを確認してください。これはコアデータの問題ではありません

問題 2: iCloud なのかアプリなのかわかりませんが、変更を同期するのに時間がかかります。1 つのデバイスで変更を加えると、別のデバイスに表示されるまでに 2 ~ 3 分かかります

2~3分で結構です。完全に同期された状態のデータを取得するには、数時間かかる場合があります。少なくとも私は半年前にこれを経験しました。

iCloud は、複数のデバイスで同時に使用するのには適していないことに注意してください。むしろ、結果整合性のようなものを提供します。

于 2012-07-13T09:22:33.697 に答える
0

あなたの例では: NSURL *iCloud = [fileManager URLForUbiquityContainerIdentifier:nil]; NSString *iCloudEnabledAppID = @"MF4HVVX5DS.Desbrina.Medicine-Tracker"; を使用します。URLForUbiquityContainerIdentifierとして

それは次のようになるはずです:

NSURL *iCloud = [fileManager URLForUbiquityContainerIdentifier: iCloudEnabledAppID];

于 2013-02-08T09:23:51.563 に答える