2015-09-01 33 views
11

OSX ve iOS için bir uygulamam var ve ikisi de aralarında temel verileri paylaşmak için iCloud kullanıyor. IPhone'da değişiklikler yaptığımda onları OSX uygulamasında görebilirim ve her iki uygulamada da NSPersistentStoreDidImportUbiquitousContentChangesNotification çağrılır, böylece iOS -> Mac iyi çalışır. Ancak Mac uygulamasında bazı değişiklikler yaptığımda onları iPhone'da göremiyorum. IPhone asla NSPersistentStoreDidImportUbiquitousContentChangesNotification'u çağırmaz. Mac'i değiştirebilmemin tek yolu iPhone'da biraz değişiklik yapmak. Sonra tüm değişiklikleri görebilirim. Her iki projede de iCloud tümleştirmesi aynıdır. Çekirdek veri veri modeli aynıdır. Haklar da aynıdır. http://ossh.com.au/design-and-technology/software-development/sample-library-style-ios-core-data-app-with-icloud-integration/iCloud Çekirdek Veri paylaşımı OSX ve iOS arasında

Neden iPhone bazı değişiklik yapmak kadar Mac değişiklikleri almıyor iPhone geçerli:

benim kod bu kütüphaneye dayanmaktadır Tüm? Herhangi bir fikir?

kullanıcı zaten iCloud bir dosya olup olmadığını kontrol iCloud sağlayan benim app

başka soru. Dosya mevcutsa, kullanıcı iCloud dosyasından temel verileri geri yüklemeyi seçebilir veya yerel mağazadan yeni kopya başlatabilir. Bu kodu kullanmak yeni bir kopya başlatmak için: her şey iyi iş gibi görünüyor tek cihazdan bu Doing

- (void)startNewCopy 
{ 
    [self removeICloudStore]; 
    [self moveStoreToIcloud]; 
} 

- (void)removeICloudStore 
{ 
    BOOL result; 
    NSError *error; 
    // Now delete the iCloud content and file 
    result = [NSPersistentStoreCoordinator removeUbiquitousContentAndPersistentStoreAtURL:[self icloudStoreURL] 
                      options:[self icloudStoreOptions] 
                      error:&error]; 
    if (!result) 
    { 
     NSLog(@"Error removing store"); 
    } 
    else 
    { 
     NSLog(@"Core Data store removed."); 
     // Now delete the local file 
     [self deleteLocalCopyOfiCloudStore]; 
    } 

} 


- (void)deleteLocalCopyOfiCloudStore { 
    // We need to get the URL to the store 
    NSError *error = nil; 
    [[NSFileManager defaultManager] removeItemAtURL:[self localUbiquitySupportURL] error:&error]; 
} 

- (void)moveStoreToIcloud 
{ 
    // Open the store 
    NSPersistentStore *sourceStore = [[_persistentStoreCoordinator persistentStores] firstObject]; 

    if (!sourceStore) 
    { 
     NSLog(@" failed to add old store"); 
    } 
    else 
    { 
     NSLog(@" Successfully added store to migrate"); 
     NSError *error; 
     id migrationSuccess = [_persistentStoreCoordinator migratePersistentStore:sourceStore toURL:[self icloudStoreURL] options:[self icloudStoreOptions] withType:NSSQLiteStoreType error:&error]; 

     if (migrationSuccess) 
     { 
      NSLog(@"Store migrated to iCloud"); 

      _persistentStoreCoordinator = nil; 
      _managedObjectContext = nil; 

      // Now delete the local file 
      [self deleteLocalStore]; 

     } 
     else 
     { 
      NSLog(@"Failed to migrate store: %@, %@", error, error.userInfo); 

     } 
    } 

} 

- (void)deleteLocalStore 
{ 
    NSError *error = nil; 
    [[NSFileManager defaultManager] removeItemAtURL:[self localStoreURL] error:&error]; 
} 

ama birden fazla cihaz ile bu çalıştığımda bazı hatalar alıyorum.

Örnek:

İki aygıtım var. İlki iCloud'a bağlı değil, ikincisi iCloud'a bağlı. Ben iCloud etkinleştirdiğinizde birinci cihaz olarak Ben startNewCopy belirledikten sonra ikinci cihazda bu hatayı alıyorum:

NSPersistentStoreCoordinatorStoresDidChangeNotification

CoreData: Ubiquity: Librarian returned a serious error for starting downloads Error Domain=BRCloudDocsErrorDomain Code=5 "The operation couldn’t be completed. (BRCloudDocsErrorDomain error 5 - No document at URL)"

hata önce hiçbir zaman denir.

Bu bildirim için benim kodudur:

Ben iCloud içeriği kaldırıldığını algılamak ve yukarıdaki hatayı almamak nasıl
- (void)processStoresDidChange:(NSNotification *)notification 
{ 
     NSLog(@"processStoresDidChange"); 
     // Post notification to trigger UI updates 

     // Check type of transition 
     NSNumber *type = [notification.userInfo objectForKey:NSPersistentStoreUbiquitousTransitionTypeKey]; 

     //NSLog(@" userInfo is %@", notification.userInfo); 
     //NSLog(@" transition type is %@", type); 

     if (type.intValue == NSPersistentStoreUbiquitousTransitionTypeInitialImportCompleted) { 

      NSLog(@" transition type is NSPersistentStoreUbiquitousTransitionTypeInitialImportCompleted"); 

     } else if (type.intValue == NSPersistentStoreUbiquitousTransitionTypeAccountAdded) { 
      NSLog(@" transition type is NSPersistentStoreUbiquitousTransitionTypeAccountAdded"); 
     } else if (type.intValue == NSPersistentStoreUbiquitousTransitionTypeAccountRemoved) { 
      NSLog(@" transition type is NSPersistentStoreUbiquitousTransitionTypeAccountRemoved"); 
     } else if (type.intValue == NSPersistentStoreUbiquitousTransitionTypeContentRemoved) { 
      NSLog(@" transition type is NSPersistentStoreUbiquitousTransitionTypeContentRemoved"); 
     } 

     [[NSOperationQueue mainQueue] addOperationWithBlock:^ { 

      if (type.intValue == NSPersistentStoreUbiquitousTransitionTypeContentRemoved) { 

       [self deleteLocalStore]; 
       _persistentStoreCoordinator = nil; 
       _managedObjectContext = nil; 

       NSLog(@" iCloud store was removed! Wait for empty store"); 
      } 

      // Refresh user Interface 
      [[NSNotificationCenter defaultCenter] postNotificationName:@"notiIcloud" object:@"storeChanged"]; 
     }]; 

} 

?

+0

Bu, sorunuzu gerçekten yanıtlamıyor, ancak Core Data'yı uzun süre önce iCloud desteği ile kullanmayı bıraktım. Daha sonra kendi senkronizasyonumu yazdım ama biraz kısıtlıydı. Sonra da Ensembles'i (http://www.ensembles.io) buldum ve o zamandan beri kullanıyordum. Benim için harika oldu. Açık kaynak kodlu bir sürümü var. Yanıt için –

+0

Thx, ancak elmadan standart iCloud desteğini kullanmayı tercih ediyorum. – user3065901

+0

Size iyi şanslar! –

cevap

0

Bana göre uygun arabirimleri kullanmıyor olabilirsiniz.

Dosyaları NSPersistentStore yöntemlerini kullanmadan iCloud içine ve dışına taşıyabilirsiniz. Genellikle uygun eylem NSFileCoordinator numaralı çağrıya da eklenmelidir.

iOS'de yaptığım şey budur. toLocal veya yerel (cihaz) deposundan bir hamle gösterir:

// 
/// Move file between stores (assumed no name clash). 
/// Return new URL. 
/// Note: cloud file moves are asynchronous. 
/// 
- (NSURL *)moveStoreFile:(NSURL *)url toRootURL:(NSURL *)rootURL toLocal:(BOOL)toLocal 
{ 
    NSURL *newURL = rootURL; 
    if (!toLocal) 
     newURL = [newURL URLByAppendingPathComponent:@"Documents"]; 
    newURL = [newURL URLByAppendingPathComponent:url.lastPathComponent]; 

    [self backupFile:url isLocal:!toLocal completionHandler: 
    ^(BOOL success) { 

     MRLOG(@"MOVE %s %@ to %s %@", toLocal? "icloud" : "local", [url lastPathComponent], 
       toLocal? "local" : "icloud", [newURL lastPathComponent]); 

     dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), 
     ^{ 
      NSError *error; 
      // setUbiquitous does file coordination 
      BOOL msuccess = [[NSFileManager defaultManager] 
          setUbiquitous:!toLocal itemAtURL:url destinationURL:newURL error:&error]; 

      dispatch_async(dispatch_get_main_queue(), 
      ^{ 
       if (!msuccess) 
        MRLOG(@"move failed: %@", error); 
       [self.delegate moveStoreFileCompletedWithStatus:success error:error]; 
      }); 
     }); 
    }]; 

    return newURL; 
} 

Deleting açık dosya koordinasyon gerektirir:

/// 
/// Purge backup file (really delete it). 
/// Note: cloud deletes are asynchronous. 
/// 
- (void)purgeFile:(NSURL *)url isLocal:(BOOL)isLocal 
{ 
    MRLOG(@"PURGE %s %@", isLocal? "local" : "icloud", [url lastPathComponent]); 

    if (isLocal) 
     [self removeFile:url]; 
    else 
     dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), 
     ^{ 
      NSError *coordinationError; 
      NSFileCoordinator *coordinator = [[NSFileCoordinator alloc] initWithFilePresenter:nil]; 

      [coordinator coordinateWritingItemAtURL:url options:NSFileCoordinatorWritingForDeleting 
                error:&coordinationError 
            byAccessor: 
      ^(NSURL* writingURL) 
      { 
       [self removeFile:writingURL]; 
      }]; 
      if (coordinationError) { 
       MRLOG(@"coordination error: %@", coordinationError); 
       [(SSApplication *)[SSApplication sharedApplication] fileErrorAlert:coordinationError]; 
      } 
     }); 
} 

Eğer NSMetadataQuery kullanıp NSMetadataQueryDidUpdateNotification için bir gözlemci eklemem gerekiyor dosyalarındaki değişiklikleri algılamak için.

0

Mac'imle iOS'u senkronize eden benzer bir sorun yaşadım.

Bu hata 5, aslında mağazanızla ilgili bir sorun olduğu anlamına gelir.

adımları deneyebilirsiniz:

  • iOS günü size Simülatörü içeriğini sıfırlamak ve ayrıca (sadece uygulama için) iCloud içeriği temizlemek gerekir.

Sen arayarak iCloud içeriği sıfırlayabilirsiniz (üzgünüm Swift içinde var): Mac OS günü

try! NSPersistentStoreCoordinator.removeUbiquitousContentAndPersistentStoreAtURL(storeURL, options: self.options) 
  • siz "Bu klasörün içeriği kaldırmak gerekir CoreDataUbiquitySupport/YourAppId ". Bu temelde Temel Veri Kalıcı Mağazanızdır (ör.: SQLite dosyası). Modeli (xcdatamodeld dosyası) değişince

Bu sorun olur ve mevcut veriler temizlenir edilmemiştir. Daha eski bir model altında oluşturulan verilere ilişkin yeni bir modele sahip olursunuz ve bu karışımı cihazlar arasında senkronize etmeye çalışıyorsunuz ...

Gelecekte, Modelle ilgili sorunu önlemek için, Temel Veri Modeli Sürümüne göz atın. ve Veri Taşıma. https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/CoreDataVersioning/Articles/Introduction.html

Sorununuzu çözdüğünü umuyorum.

İlgili konular