2011-10-21 49 views
31

我已經有一個iPhone應用程序將數據存儲在本地文檔文件夾中的文件中。現在我瞭解了iCloud技術,我的第一個問題是:有時我會在檢查新版本時使用iCloud作爲目錄嗎?如何使用iCloud存儲和同步應用程序文件

我的意思是:我可以避免使用UIDocument,文件協調員和文件演示者?我只想知道是否可以像特殊文件夾一樣對待iCloud,並只使用NSFileManager來推送和檢索文件。

最後說明:我不使用Core Data或任何數據庫,我只有一個數據文件。

編輯:

我已經讀了蘋果官方的iCloud文檔,所以不要聯繫我給他們。我只需要一些代碼示例。

回答

15

我知道你的感受,iCloud有點令人生畏。但是,我認爲UIDocument,文件協調器等是無法實現的,只是簡單地使用iCloud作爲簡單的文件夾。

如果你正在尋找一個易於理解的示例代碼,請看看這篇文章:

iCloud basics and code sample

我包括覆蓋iCloud中的裸最小值和幾乎使用完整的示例代碼它就像一個目錄。也許這使得你使用UIDocument,文件協調器等更簡單。

但是,和你一樣,我希望有一個更好的,更老的紀錄片文件​​夾的想法更容易和更兼容的方式。但是,由於這是iCloud,並且iCloud會做更多的事情(比如讓不同設備上的所有內容保持同步,不斷更新到雲端等),所以UIDocument等將無法實現。

+0

我同意,如果你說沒有辦法,我會閱讀教程。但我認爲應該有一種更簡單的方法來做到這一點,就像在應用沙箱中編寫或讀取文件時一樣。謝謝 – edo42

+0

感謝您的鏈接。 – Shajo

24

對我來說「有效」只是簡單的:

NSFileManager *fm = [NSFileManager defaultManager]; 

NSURL *ubiq = [[NSFileManager defaultManager] URLForUbiquityContainerIdentifier:nil]; 

if (ubiq == nil) { 
    return NO; 
} 

NSError *theError = nil; 

[fm setUbiquitous:true itemAtURL:backupUrl destinationURL:[[ubiq URLByAppendingPathComponent:@"Documents" isDirectory:true] URLByAppendingPathComponent:backupName] error:&theError]; 

蘋果說要調用非UI線程。讓文件「移動」。

self.query = [[NSMetadataQuery alloc] init]; 
[self.query setSearchScopes:[NSArray arrayWithObject:NSMetadataQueryUbiquitousDocumentsScope]]; 
NSPredicate *pred = [NSPredicate predicateWithFormat: @"%K like '*.db'", NSMetadataItemFSNameKey]; 
[self.query setPredicate:pred]; 
[[NSNotificationCenter defaultCenter] addObserver:self 
             selector:@selector(queryDidFinishGathering:) 
              name:NSMetadataQueryDidFinishGatheringNotification 
              object:self.query]; 

[self.query startQuery]; 

- (void)queryDidFinishGathering:(NSNotification *)notification { 
    NSMetadataQuery *query = [notification object]; 
    [query disableUpdates]; 
    [query stopQuery]; 

    [self loadData:query]; 

    [[NSNotificationCenter defaultCenter] removeObserver:self name:NSMetadataQueryDidFinishGatheringNotification object:query]; 

    self.query = nil; 
} 

枚舉的樣品通過查詢結果:

- (void)loadData:(NSMetadataQuery *)query { 
    [self.backups removeAllObjects]; 

    for (NSMetadataItem *item in [query results]) { 
     NSURL *url = [item valueForAttribute:NSMetadataItemURLKey]; 
     [self.backups addObject:url.lastPathComponent]; 
    } 

    [_table reloadData]; 

    [self.loadingBackupIndicator stopAnimating]; 
    self.loadingIndicatorLabel.text = [NSString stringWithFormat: @"%d backups found", [self.backups count]]; 
} 

,並開始了具體的文件 「下載」:

NSFileManager *fm = [NSFileManager defaultManager]; 

NSURL *ubiq = [[NSFileManager defaultManager] URLForUbiquityContainerIdentifier:nil]; 

if (ubiq == nil) { 
    return NO; 
} 

NSError *theError = nil; 

bool started = [fm startDownloadingUbiquitousItemAtURL:[[ubiq URLByAppendingPathComponent:@"Documents" isDirectory:true] URLByAppendingPathComponent:backupName] error:&theError]; 

NSLog(@"started download for %@ %d", backupName, started); 

if (theError != nil) { 
    NSLog(@"iCloud error: %@", [theError localizedDescription]); 
} 

您可以通過NSMetaDataQuery這樣的查詢他們檢查文件「正在下載」:

- (BOOL)downloadFileIfNotAvailable { 
    NSNumber *isIniCloud = nil; 

    NSURL *ubiq = [[NSFileManager defaultManager] URLForUbiquityContainerIdentifier:nil]; 

    NSURL *file = [[ubiq URLByAppendingPathComponent:@"Documents" isDirectory:true] URLByAppendingPathComponent:self.backupName]; 

    if ([file getResourceValue:&isIniCloud forKey:NSURLIsUbiquitousItemKey error:nil]) { 
     // If the item is in iCloud, see if it is downloaded. 
     if ([isIniCloud boolValue]) { 
      NSNumber* isDownloaded = nil; 
      if ([file getResourceValue:&isDownloaded forKey:NSURLUbiquitousItemIsDownloadedKey error:nil]) { 
       if ([isDownloaded boolValue]) { 
        [self.loadingBackupIndicator stopAnimating]; 
        self.loadingIndicatorLabel.text = @"Downloaded"; 

        .... 

        [[NSFileManager defaultManager] copyItemAtPath:[file path] toPath:restorePath error:&theError ]; 

        .... 

        return YES; 
       } 

       self.loadingCheckTimer = [NSTimer timerWithTimeInterval:3.0f target:self selector:@selector(downloadFileIfNotAvailable) userInfo:nil repeats:NO]; 
       [[NSRunLoop currentRunLoop] addTimer:self.loadingCheckTimer forMode:NSDefaultRunLoopMode]; 

       return NO; 
      } 
     } 
    } 

    return YES; 
} 

我沒想到代碼會很長,並且很抱歉在這裏提供非常原始的代碼片斷。沒有意圖說出上述可以是代碼的生產質量,只是分享這個概念。

我還沒有提交了我的應用程序的蘋果裏面,所以看不出來,這將是「認可」的應用程序商店(如果他們發現或護理...)

+3

只是爲了說明上述代碼的「生產」版本將其在應用程序內部傳遞給應用程序商店。 –

+1

你能否請你提供一個示例項目,包括上面的代碼。請幫助我,如果有可能的話。 – Gypsa

+0

@StanislavDvoychenko先生您好先生給我一些關於icloud編碼部分的想法.means如何strore和retrive等提前。感謝提前 – Bajaj

14

您可以上傳單個文件到使用NSFileManager的iCloud。我張貼在如何做到這一點上我的博客complete walkthrough,但這裏的相關的NSFileManager代碼:

NSURL *destinationURL = [self.ubiquitousURL URLByAppendingPathComponent:@"Documents/image.jpg"] 
[[NSFileManager defaultManager] setUbiquitous:YES 
            itemAtURL:sourceURL 
           destinationURL:destinationURL 
             error:&error] 
+0

有沒有辦法複製而不是移動? – jjxtra

+1

當我這樣做時,我嘗試使用residentData = [[NSMutableArray alloc] initWithContentsOfURL:icloudURL]獲取iCloud中的文件; 但每次都會返回零。 – coolcool1994

-1

使用此代碼:

+ (NSString *)Pathsave { 
    NSString *os5 = @"5.0"; 

    NSString *currSysVer = [[UIDevice currentDevice] systemVersion]; 
    NSString *path = [NSHomeDirectory() stringByAppendingPathComponent:@"Documents"]; 

    if ([currSysVer compare:os5 options:NSNumericSearch] == NSOrderedAscending) { 
     // Lower than 4 
     return path; 
    } else if ([currSysVer compare:os5 options:NSNumericSearch] == NSOrderedDescending) { 
     // 5.0.1 and above   
     return path; 
    } else { 
     // iOS 5 
     path = [NSHomeDirectory() stringByAppendingPathComponent:@"Library/Caches"]; 
     return path; 
    } 

    return nil; 
} 
6

是不是真的用左右一UIDocument方式。我試圖在第一次使用iCloud的時候這樣做,但事實證明這是一場沒有UIDocument的災難。起初使用UIDocument看起來像很多額外的工作,但事實並非如此。

你可以很容易地在一小時內將UIDocument子類化,並讓它與任何類型的文件一起工作(只需將content屬性設置爲NSData)。它還在標準文件系統提供了許多好處:

  • 更改跟蹤
  • 文件解決衝突
  • 文件的國家支持
  • 增強保存/打開/關閉功能

老實說,支出只需一兩個小時閱讀Apple文檔,然後使用它就非常值得花時間和大腦力量。關於iCloud文檔存儲的優秀初始文章可以在Apple's Developer Documentation中找到。


我已經寫了一個UIDocument的子類,它可以處理任何類型的文件(特別是NSData)。您可以在GitHub上查看,下載和修改UIDocument子類的代碼。

創建文檔:

// Initialize a document with a valid file path 
iCloudDocument *document = [[iCloudDocument alloc] initWithFileURL:fileURL]; 

// Set the content of the document 
document.contents = content; 

// Increment the change count 
[document updateChangeCount:UIDocumentChangeDone]; 

保存現有的文檔:

// Save and close the document 
[document closeWithCompletionHandler:nil]; 

保存新文檔:

[document saveToURL:document.fileURL forSaveOperation:UIDocumentSaveForCreating completionHandler:nil]; 

您還可以同步方式使用存儲中的iCloud所有文件NSMetadataQuery。 Apple提供了一個非常好的使用NSMetadata查詢來同步應用程序文件的例子。還請確保在執行這些操作之前檢查iCloud(提示:在NSFileManager上使用ubiquityIdentityToken方法)。


您可能還想考慮使用開源庫,如iCloud Document Sync。 iCloud Document Sync項目使得存儲和同步應用文件變得非常簡單:

使用單行代碼方法將iCloud集成到iOS文檔項目中。快速輕鬆地同步,上傳,管理和刪除iCloud中的文檔。有助於讓iCloud「爲開發者工作」。

在幾乎所有的iCloud Document Sync方法中,您只需傳入文件數據作爲參數,然後處理其餘部分(保存,同步等)。

免責聲明:我是開源項目iCloud Document Sync的貢獻開發人員。不過,我相信這個項目會對你有好處,並且與這個問題有關。這不是促銷或廣告。

+0

這就是我最後做的。 – edo42

+0

如果您的用例是將數據轉儲到iCloud中,則可以使用文件協調器來完成此操作,並且不需要UIDocument。 – Andy

相關問題