2013-01-06 9 views
6

Próbuję przesłać lokalny folder pełen dokumentów do zdalnego folderu iCloud. Napisałem tę metodę, aby przechwytywać tablicę plików w folderze lokalnym, sprawdzać, czy już istnieją, a jeśli nie istnieją, przesłać je do iCloud. Uwaga: ten kod jest wykonywany w wątku tła, a nie w wątku głównym.Dokumenty, które nie są przesyłane do usługi iCloud podczas używania pętli - iOS

//Get the array of files in the local documents directory 
NSString *documentsDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0]; 
NSArray *localDocuments = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:documentsDirectory error:nil]; 

//Compare the arrays then upload documents not already existent in iCloud 
for (int item = 0; item < [localDocuments count]; item++) { 
    //If the file does not exist in iCloud, upload it 
    if (![[iCloud previousQueryResults] containsObject:[localDocuments objectAtIndex:item]]) { 
      NSLog(@"Uploading %@ to iCloud...", [localDocuments objectAtIndex:item]); 
      //Move the file to iCloud 
      NSURL *destinationURL = [[[NSFileManager defaultManager] URLForUbiquityContainerIdentifier:nil] URLByAppendingPathComponent:[NSString stringWithFormat:@"Documents/%@",[localDocuments objectAtIndex:item]]]; 
      NSError *error; 
      NSURL *directoryURL = [[NSURL alloc] initWithString:[documentsDirectory stringByAppendingPathComponent:[localDocuments objectAtIndex:item]]]; 
      BOOL success = [[NSFileManager defaultManager] setUbiquitous:YES itemAtURL:directoryURL destinationURL:destinationURL error:&error]; 
      if (success == NO) { 
       //Determine Error 
       NSLog(@"%@",error); 
      } 
    } else { 
      ... 
    } } 

Kiedy uruchomić ten kod Pętla dla prowadzenia prac w porządku - używam sprawozdania NSLog aby dowiedzieć się, który plik jest przesyłając - i każdy plik przechowywany lokalnie, który nie jest już w iCloud ma rozpocząć ładowanie . Po zakończeniu pętli For Check sprawdzam, które dokumenty są teraz w iCloud, używając developer.icloud.com. Tylko jeden plik (plik sqlite, który moja aplikacja ciągle robi, ale nigdy nie korzysta) z wielu przechowywanych lokalnie ładowań do iCloud. Dlaczego przesyłano tylko jeden plik podczas korzystania z pętli?

Kiedy używam tego samego kodu do przesyłania pojedynczych plików (bez pętli For Loop), oni ładują się idealnie do iCloud. Dlaczego funkcja For Loop utrudni przesyłanie plików? Czy ma to związek z pętlą For Loop przechodzącą do następnego wiersza kodu bez czekania na zakończenie ostatniego procesu/linii? Co tu się dzieje?

EDIT: Zwykle kiedy mogę przesłać duże pliki do iCloud (bez użycia pętli for) Widzę na stronie dev iCloud, że plik jest w toku Upload niemal natychmiast. Testuję wszystko przez WiFi i czekam chwilę, ale nic się nie pojawia (z wyjątkiem pliku sqlite).

EDYCJA: Sprawdzam również dostępność usługi iCloud w innej metodzie, która następnie pozwala na połączenia z tą metodą, jeśli usługa iCloud jest dostępna. Przeczytałem również dokumentację i obejrzałem filmy WWDC na stronie Apple, jednak są one złożone i nie dostarczają wielu wyjaśnień na temat tego, co próbuję zrobić.

EDIT Po rewizji kodu powyżej (dodanie funkcjonalności błędzie), teraz ten komunikat o błędzie w dzienniku:

Error Domain=NSCocoaErrorDomain Code=512 "The operation couldn’t be completed. (Cocoa error 512.)" UserInfo=0x1f5dd070 {NSUnderlyingError=0x208ad9b0 "The operation couldn’t be completed. (LibrarianErrorDomain error 2 - No source URL specified.)"} 

To czyni sprawę jeszcze bardziej mylące, ponieważ jeden z plików przesłanych pomyślnie , podczas gdy inne nie.

+0

Bez szczegółowego sprawdzania kodu, zapytam, jak długo czekasz, aby sprawdzić, czy zostały przesłane? iCloud nie jest natychmiastowym przesyłaniem przez twoją aplikację, ale demonem tła, który zsynchronizuje treść "ostatecznie". Teraz "ostatecznie" jest zwykle cholernie szybkie, ale nie jest szybkie. –

+0

Dobra uwaga, jednak zazwyczaj kiedy przesyłam duże pliki do iCloud (bez użycia pętli For For Loop), widzę na stronie internetowej iCloud, że plik * Oczekuje na przesłanie * prawie natychmiast. Testuję wszystko przez WiFi i czekam chwilę, ale nic się nie pojawia (z wyjątkiem pliku sqlite). –

+2

Czy sprawdzasz, czy wywołanie 'setUbiquitous' zwraca" TAK ", i dlaczego nie sprawdzasz i stwierdza błędy, jeśli zwraca" NO "? Istnieje powód, dla którego metoda ma parametr "błąd". –

Odpowiedz

6

OK, ta ostatnia edycja jest przydatna. Błąd polega na tym, że brakuje źródłowego adresu URL (directoryURL w kodzie) - prawdopodobnie dlatego, że jest to nil. Dlaczego miałby to być nil? Ponieważ tworzysz to źle. Używasz -[NSURL initWithString:] i docs powiedzieć, że:

This string must conform to URL format as described in RFC 2396. This method parses URLString according to RFCs 1738 and 1808.

jesteś przechodząc ścieżką pliku, a nie URL. Jeśli podasz NSURL coś, co nie rozpoznaje jako prawidłowy URL, zwykle zwraca nil. Wygląda na to, że NSURL często generuje adres URL pliku, ale niepowodzenie jest tutaj oczekiwanym zachowaniem. Z tego, co wiem, wydaje się działać, jeśli nazwa pliku nie zawiera spacji, ale nie jest to udokumentowane, a nie coś, na czym można polegać.

Należy zmienić wiersz, w którym należy zainicjować directoryURL, aby użyć czegoś, co akceptuje ścieżkę pliku. Coś jak:

NSURL *directoryURL = [NSURL fileURLWithPath:[documentsDirectory stringByAppendingPathComponent:[localDocuments objectAtIndex:item]]]; 

Ponadto, upewnij się, aby sprawdzić, czy nie jest directoryURLnil, na wszelki wypadek.

+2

Albo jeszcze lepiej bezpośrednio użyć metod, które zwracają adresy URL zamiast pracować ze ścieżkami i konwertować je na adresy URL później. – Sven

+0

Dobrze, przełączenie na 'contentsOfDirectoryAtURL: includingPropertiesForKeys: options: error:' również wykona zadanie. –

Powiązane problemy