2012-07-12 108 views
0

我一直在尋找使用iCloud獲得核心數據,以便人們可以從多個設備訪問數據。 我一直在跟着本教程(http://timroadley.com/)儘可能最好的突破我的應用程序,但我遇到了一些問題。iOS核心數據存儲在iCloud中與其他設備同步

問題1:當應用程序被關閉(不只是暫停),並重新開放是沒有在表中顯示,所以以前的數據似乎並沒有得到加載

問題2:我不知道如果它的iCloud或應用程序,但它需要年齡來同步更改。我在一臺設備上的變化,它需要2-3分鐘,可以在其他

誰能幫我解決這兩個問題,請

此代碼是我的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]; 
} 

回答

1

問題1:當應用程序被關閉(不只是暫停),並重新開放是沒有在表中顯示,所以以前的數據似乎並沒有得到加載

檢查你的所有數據保存到你的管理對象上下文。這不應該是核心數據的問題

問題2:我不知道,如果它的iCloud或應用程序,但它需要年齡同步的變化。我在一臺設備上的變化,它需要2-3分鐘,可以在其他

2-3分鐘是真的沒事。有時需要幾小時才能使數據處於完全同步狀態。至少我在半年前遇到過這種情況。

請記住,iCloud不適合在多個設備上同時使用。它提供了最終的一致性。在你的例子中:

+0

所有調用保存上下文,進行更改或退出應用程序。我已將保存上下文添加到第一篇文章 – 2012-07-13 14:44:39

0

NSURL * iCloud = [fileManager URLForUbiquityContainerIdentifier:nil]; 使用您的 NSString * iCloudEnabledAppID = @「MF4HVVX5DS.Desbrina.Medicine-Tracker」; 作爲URLForUbiquityContainerIdentifier

它應該是這樣的:

NSURL *的iCloud = [文件管理URLForUbiquityContainerIdentifier:iCloudEnabledAppID];