2014-11-20 18 views
8

Chcę, aby moja aplikacja zapisywała utworzone przez siebie dokumenty na dysku iCloud, ale mam trudności z śledzeniem tego, co napisał Apple. Oto, co mam do tej pory, ale nie jestem pewien, dokąd się udać.Zapisywanie dokumentów iOS 8 na dysku iCloud

Update2

Mam następujących w moim kodu ręcznie zapisać dokument na dysku iCloud:

- (void)initializeiCloudAccessWithCompletion:(void (^)(BOOL available)) completion { 
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 
     self.ubiquityURL = [[NSFileManager defaultManager] URLForUbiquityContainerIdentifier:nil]; 
     if (self.ubiquityURL != nil) { 
      dispatch_async(dispatch_get_main_queue(), ^{ 
       NSLog(@"iCloud available at: %@", self.ubiquityURL); 
       completion(TRUE); 
      }); 
     } 
     else { 
      dispatch_async(dispatch_get_main_queue(), ^{ 
       NSLog(@"iCloud not available"); 
       completion(FALSE); 
      }); 
     } 
    }); 
} 
if (buttonIndex == 4) { 



    [self initializeiCloudAccessWithCompletion:^(BOOL available) { 

     _iCloudAvailable = available; 

     NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); 

     NSString *documentsDirectory = [paths objectAtIndex:0]; 

     NSString *pdfPath = [documentsDirectory stringByAppendingPathComponent:selectedCountry]; 

     NSURL* url = [NSURL fileURLWithPath: pdfPath]; 


     [self.manager setUbiquitous:YES itemAtURL:url destinationURL:self.ubiquityURL error:nil]; 


    }]; 

     } 

mam uprawnienia ustanowione dla identyfikatora aplikacji iw samym Xcode. Klikam przycisk, aby zapisać na iCloud Drive, i nie pojawiają się żadne błędy, aplikacja nie ulega awarii, ale nic nie pojawia się na moim Macu w iCloud Drive. Aplikacja działa na moim iPhone 6 Plus przez Test Flight podczas korzystania z iOS 8.1.1.

Gdybym go uruchomić w symulatorze (wiem, że to nie będzie działać z powodu iCloud napęd nie działa z symulatorem), pojawia się błąd awarii: 'NSInvalidArgumentException', reason: '*** -[__NSPlaceholderDictionary initWithObjects:forKeys:count:]: attempt to insert nil object from objects[3]'

+0

'setUbiquitous: itemAtURL: destinationUrl: error:' zwraca BOOL, czy operacja się powiodła, czy nie. Jaka jest wartość zwracana? Podaj także wskaźnik do obiektu 'NSError' dla parametru' error'. Jeśli metoda zwróci wartość NIE, prawdopodobnie zapewni to dodatkowe wskazówki. – fguchelaar

+0

@fguchelaar Przepraszam, że nigdy nie zawiedliśmy zbyt wiele przy pomocy NSFileManager, więc niektóre z nich są nad moją głową. – user717452

Odpowiedz

29

Cóż, masz mnie interesuje w tej sprawie ja i wskutek sposób spędziłem dużo czasu na to pytanie, ale teraz, Mam to działa, mam nadzieję, że to ci pomoże!

File on my Mac

Aby zobaczyć, co faktycznie dzieje się w tle, można rzucić okiem na ~/Library/Mobile Documents/, ponieważ jest to folder, w którym pliki w końcu pokaże się. Kolejnym bardzo fajnym narzędziem jest brctl, aby monitorować, co dzieje się na twoim macu po zapisaniu pliku w iCloud. Uruchom brctl log --wait --shorten z okna terminala, aby uruchomić dziennik.

Pierwszą rzeczą, którą należy zrobić po włączeniu zdolności iCloud (z wybranymi dokumentami iCloud), jest podanie informacji na temat obsługi iCloud Drive Support (Enabling iCloud Drive Support). Musiałem również podnieść wersję pakietu przed ponownym uruchomieniem aplikacji; zabrał mi trochę czasu, aby to rozgryźć. Dodaj następujące do info.plist:

<key>NSUbiquitousContainers</key> 
<dict> 
    <key>iCloud.YOUR_BUNDLE_IDENTIFIER</key> 
    <dict> 
     <key>NSUbiquitousContainerIsDocumentScopePublic</key> 
     <true/> 
     <key>NSUbiquitousContainerSupportedFolderLevels</key> 
     <string>Any</string> 
     <key>NSUbiquitousContainerName</key> 
     <string>iCloudDriveDemo</string> 
    </dict> 
</dict> 

Następna w kolejce, kod:

- (IBAction)btnStoreTapped:(id)sender { 
    // Let's get the root directory for storing the file on iCloud Drive 
    [self rootDirectoryForICloud:^(NSURL *ubiquityURL) { 
     NSLog(@"1. ubiquityURL = %@", ubiquityURL); 
     if (ubiquityURL) { 

      // We also need the 'local' URL to the file we want to store 
      NSURL *localURL = [self localPathForResource:@"demo" ofType:@"pdf"]; 
      NSLog(@"2. localURL = %@", localURL); 

      // Now, append the local filename to the ubiquityURL 
      ubiquityURL = [ubiquityURL URLByAppendingPathComponent:localURL.lastPathComponent]; 
      NSLog(@"3. ubiquityURL = %@", ubiquityURL); 

      // And finish up the 'store' action 
      NSError *error; 
      if (![[NSFileManager defaultManager] setUbiquitous:YES itemAtURL:localURL destinationURL:ubiquityURL error:&error]) { 
       NSLog(@"Error occurred: %@", error); 
      } 
     } 
     else { 
      NSLog(@"Could not retrieve a ubiquityURL"); 
     } 
    }]; 
} 

- (void)rootDirectoryForICloud:(void (^)(NSURL *))completionHandler { 

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 
     NSURL *rootDirectory = [[[NSFileManager defaultManager] URLForUbiquityContainerIdentifier:nil]URLByAppendingPathComponent:@"Documents"]; 

     if (rootDirectory) { 
      if (![[NSFileManager defaultManager] fileExistsAtPath:rootDirectory.path isDirectory:nil]) { 
       NSLog(@"Create directory"); 
       [[NSFileManager defaultManager] createDirectoryAtURL:rootDirectory withIntermediateDirectories:YES attributes:nil error:nil]; 
      } 
     } 

     dispatch_async(dispatch_get_main_queue(), ^{ 
      completionHandler(rootDirectory); 
     }); 
    }); 
} 

- (NSURL *)localPathForResource:(NSString *)resource ofType:(NSString *)type { 
    NSString *documentsDirectory = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0]; 
    NSString *resourcePath = [[documentsDirectory stringByAppendingPathComponent:resource] stringByAppendingPathExtension:type]; 
    return [NSURL fileURLWithPath:resourcePath]; 
} 

Mam plik o nazwie demo.pdf przechowywane w folderze Documents, który Będę 'przesyłania'.

będę podkreślić kilka części:

URLForUbiquityContainerIdentifier: zapewnia główny katalog do przechowywania plików, jeśli chcesz się do nich, aby pokazać się w de iCloud dysku na komputerze Mac, a następnie trzeba je przechowywać w folderze Dokumenty , więc tutaj możemy dodać ten folder do korzeni:

NSURL *rootDirectory = [[[NSFileManager defaultManager] URLForUbiquityContainerIdentifier:nil]URLByAppendingPathComponent:@"Documents"]; 

Należy również dodać nazwę pliku na adres URL, tutaj skopiować pliku z localURL (co jest demo.pdf):

// Now, append the local filename to the ubiquityURL 
ubiquityURL = [ubiquityURL URLByAppendingPathComponent:localURL.lastPathComponent]; 

I to w zasadzie to ...

Jako bonus, sprawdź w jaki sposób można zapewnić NSError wskaźnik uzyskać potencjalną informację o błędzie:

// And finish up the 'store' action 
NSError *error; 
if (![[NSFileManager defaultManager] setUbiquitous:YES itemAtURL:localURL destinationURL:ubiquityURL error:&error]) { 
    NSLog(@"Error occurred: %@", error); 
} 
+0

Wygląda na to, że wysyłam plik (pojawia się błąd: plik już istnieje, gdy próbuję pisać ten sam plik wiele razy), i widzę rzeczy w "brutalnym logu" na moim Macu, ale nie wiem. t zobacz folder na iCloud.com lub na moim Macu. Wszelkie przemyślenia, dlaczego tak się stało? –

+2

EDYCJA: Musiał zwiększyć wartość 'CFBundleVersion'. Szalony! http://stackoverflow.com/a/25328864/1148702 –

+0

Wiem, szaleństwo .. Podkreślę, że nieco to moja odpowiedź, więcej, wydaje się, że przeoczyłeś to :) – fguchelaar

1

Jeśli masz zamiar pracować z UIDocument i iCloud ten przewodnik od Apple jest bardzo dobry: https://developer.apple.com/library/ios/documentation/DataManagement/Conceptual/UsingCoreDataWithiCloudPG/Introduction/Introduction.html

EDITED: nie znam żadnego lepszego przewodnika strony, więc może to pomoże:

trzeba będzie pobrać ubiquityURL korzystając t on URLForUbuiquityContainerIdentifier funkcja na NSFileManager (która powinna być wykonana asynchronicznie). Po wykonaniu tej czynności można użyć kodu podobnego do poniższego, aby utworzyć dokument.

NSString* fileName = @"sampledoc"; 
NSURL* fileURL = [[self.ubiquityURL URLByAppendingPathComponent:@"Documents" isDirectory:YES] URLByAppendingPathComponent:fileName isDirectory:NO]; 

UIManagedDocument* document = [[UIManagedDocument alloc] initWithFileURL:fileURL]; 

document.persistentStoreOptions = @{ 
        NSMigratePersistentStoresAutomaticallyOption : @(YES), 
        NSInferMappingModelAutomaticallyOption: @(YES), 
        NSPersistentStoreUbiquitousContentNameKey: fileName, 
        NSPersistentStoreUbiquitousContentURLKey: [self.ubiquityURL URLByAppendingPathComponent:@"TransactionLogs" isDirectory:YES] 
}; 

[document saveToURL:fileURL forSaveOperation:UIDocumentSaveForCreating completionHandler:^(BOOL success) { 

}]; 

Będziesz także zajrzeć do korzystania NSMetadataQuery wykryć dokumenty przesłane z innych urządzeń i potencjalnie kolejce je do pobrania, a obserwując NSPersistentStoreDidImportUbiquitousContentChangesNotification znaleźć o zmianach dokonanych za pośrednictwem iCloud, między innymi.

** Edycja 2 **

Wygląda jak próbujesz zapisać plik PDF, który nie jest całkiem co firmy Apple rozważa „dokument” w kategoriach iCloud synchronizacji. Nie trzeba używać UIManagedDocument. Usuń 3 ostatnie wiersze procedury obsługi zakończenia, a zamiast tego użyj funkcji NSFileManager o setUbiquitous:itemAtURL:destinationURL:error:. Pierwszy URL powinien być lokalną ścieżką do pliku PDF. Drugi adres URL powinien być ścieżką wewnątrz kontenera ubikwywności, aby zapisać jako.

Być może będziesz musiał również zajrzeć do NSFileCoordinator. myślę, że ten przewodnik od Apple może być najbardziej istotne: https://developer.apple.com/library/ios/documentation/FileManagement/Conceptual/FileSystemProgrammingGuide/iCloud/iCloud.html

+1

To trochę pomocne, po prostu nie śledzę tego, jak Apple pisze wszystkie swoje rzeczy. Po prostu szukam czegoś, co mówi, kiedy robisz swój dokument, robisz to i to, aby przechowywać go w iCloud, aby pojawił się na iCloud Drive. – user717452

+0

Sprawdź aktualizację oryginalnego pytania, aby sprawdzić, czy coś mi nie pasuje. – user717452

+0

Mam to teraz zapisywanie pliku Metadata.plist na dysku iCloud, ale nie sam plik PDF. Co jest popsute? – user717452