我如何在 iCloud 中保存 NSData

Posted

技术标签:

【中文标题】我如何在 iCloud 中保存 NSData【英文标题】:How can i save NSData in iCloud 【发布时间】:2013-03-04 09:41:45 【问题描述】:

我的应用程序中有 NSData,我想将这些数据保存在 iCloud 中。 我不想将我的 NSUserDefaults 与 iCloud 同步,所以它没有“Can I use iCloud to sync the NSUserDefaults plist file”的克隆。 那可能吗?我怎样才能做到这一点?如何检索已保存的数据?

【问题讨论】:

【参考方案1】:

是的,这是可能的。我以前做过,我的答案是syncing zip with iCloud,我正在创建 zip 并将其转换为 NSData 并与 iCloud 同步,稍后我收到 NSData 并再次将其转换回 zip 并解压缩内容。在这里,您的主要需求是同步 NSData,因此您可以为NSData 工作。

1) 创建UIDocument的子类

#import <UIKit/UIKit.h>

@interface MyDocument : UIDocument
    @property (strong) NSData *dataContent;
@end

2) 我的文档.m

#import "MyDocument.h"

@implementation MyDocument
@synthesize dataContent;

// Called whenever the application reads data from the file system
- (BOOL)loadFromContents:(id)contents ofType:(NSString *)typeName error:(NSError **)outError

    self.dataContent = [[NSData alloc] initWithBytes:[contents bytes] length:[contents length]];
    [[NSNotificationCenter defaultCenter] postNotificationName:@"noteModified" object:self];
    return YES;     


// Called whenever the application (auto)saves the content of a note
- (id)contentsForType:(NSString *)typeName error:(NSError **)outError 

    return self.dataContent;


@end

3) 与 iCloud 同步(您可以根据需要进行操作)

-(IBAction) iCloudSyncing:(id)sender


    NSURL* ubiq = [[NSFileManager defaultManager]URLForUbiquityContainerIdentifier:nil];
    NSURL *ubiquitousPackage = [[ubiq URLByAppendingPathComponent:@"Documents"]  URLByAppendingPathComponent:@"iCloudPictures.zip"];

    MyDocument *mydoc = [[MyDocument alloc] initWithFileURL:ubiquitousPackage];
    NSData *data = << YOUR NSDATA >>;
    mydoc.dataContent = data;

    [mydoc saveToURL:[mydoc fileURL] forSaveOperation:UIDocumentSaveForCreating completionHandler:^(BOOL success)
     
         if (success)
         
             NSLog(@"Synced with icloud");
         
         else
             NSLog(@"Syncing FAILED with icloud");

     ];

希望这会有所帮助..

【讨论】:

如果contents 响应byteslength,不就是一个NSData 本身吗?在这种情况下,您可以发送 copy 并在它是不可变数据对象时为自己保存一份副本。 @OfirMalachi 请在下面查看我的回答。【参考方案2】:
// 1. Any file can be uploaded to iCloud container of any size (yes you should be having that much of space in iCloud) lets take an example SampleData.zip

    // 2. This method will upload or sync SampleData.zip file in iCloud container, iCloud actually checks the metadata of your file before it uploads it into your iCloud container (so for first time it will upload the file and from next time it will only upload the changes)

    -(void) iCloudSyncing:(id)sender
    
        //Doc dir
        NSString *documentsDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
        NSString *filePath = [documentsDirectory stringByAppendingPathComponent:@"SampleData.zip"];
        NSURL *u = [[NSURL alloc] initFileURLWithPath:filePath];
        NSData *data = [[NSData alloc] initWithContentsOfURL:u];

        //Get iCloud container URL
        NSURL *ubiq = [[NSFileManager defaultManager]URLForUbiquityContainerIdentifier:nil];// in place of nil you can add your container name
        //Create Document dir in iCloud container and upload/sync SampleData.zip
        NSURL *ubiquitousPackage = [[ubiq URLByAppendingPathComponent:@"Documents"]URLByAppendingPathComponent:@"SampleData.zip"];
        Mydoc = [[MyDocument alloc] initWithFileURL:ubiquitousPackage];
        Mydoc.zipDataContent = data;

        [Mydoc saveToURL:[Mydoc fileURL] forSaveOperation:UIDocumentSaveForCreating completionHandler:^(BOOL success)
         
             if (success)
             
                 NSLog(@"SampleData.zip: Synced with icloud");
             
             else
                 NSLog(@"SampleData.zip: Syncing FAILED with icloud");

         ];
    



      // 3 Download data from the iCloud Container

    - (IBAction)GetData:(id)sender 

        //--------------------------Get data back from iCloud -----------------------------//
        id token = [[NSFileManager defaultManager] ubiquityIdentityToken];
        if (token == nil)
        
            NSLog(@"ICloud Is not LogIn");
        
        else
        
            NSLog(@"ICloud Is LogIn");

            NSError *error = nil;
            NSURL *ubiq = [[NSFileManager defaultManager]URLForUbiquityContainerIdentifier:nil];// in place of nil you can add your container name
            NSURL *ubiquitousPackage = [[ubiq URLByAppendingPathComponent:@"Documents"]URLByAppendingPathComponent:@"SampleData.zip"];
            BOOL isFileDounloaded = [[NSFileManager defaultManager]startDownloadingUbiquitousItemAtURL:ubiquitousPackage error:&error];
            if (isFileDounloaded) 
                NSLog(@"%d",isFileDounloaded);
                NSString *documentsDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
                //changing the file name as SampleData.zip is already present in doc directory which we have used for upload
                NSString* fileName = [NSString stringWithFormat:@"RecSampleData.zip"];
                NSString* fileAtPath = [documentsDirectory stringByAppendingPathComponent:fileName];
                NSData *dataFile = [NSData dataWithContentsOfURL:ubiquitousPackage];
                BOOL fileStatus = [dataFile writeToFile:fileAtPath atomically:NO];
                if (fileStatus) 
                    NSLog(@"success");
                
            
            else
                NSLog(@"%d",isFileDounloaded);
            
        
    

    //4 voila its done :)

【讨论】:

【参考方案3】:

1) Converting data into zip file and then saving to icloud

2) saving a xml file to icloud

这里有解决方案将数据保存在 icloud 中,否则我们可以将数据写入文件,我们可以通过提供文件路径直接将该文件保存到 icloud

【讨论】:

【参考方案4】:

用于自定义对象注意:每个 iCloud 用户仅限 1 MB!

+(void)write

//Decode using
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:[HistoryFile files]];

//Save Data To NSUserDefault
NSUbiquitousKeyValueStore *iCloud =  [NSUbiquitousKeyValueStore defaultStore];

//let ios know we want to save the data    
[iCloud setObject:data forKey:@"app_data"];


//iOS will save the data when it is ready.
[iCloud synchronize];




+(NSMutableArray*)read
    //Read Settings Value From NSUserDefault
    //get the NSUserDefaults object

    NSUbiquitousKeyValueStore *iCloud =  [NSUbiquitousKeyValueStore defaultStore];
    //read value back from the settings
    NSData *data = [iCloud objectForKey:@"app_data"];
    NSMutableArray *data_array = (NSMutableArray*)[NSKeyedUnarchiver unarchiveObjectWithData:data];    
    NSLog(@"data_array %@",data_array);
    return data_array;

【讨论】:

NSUbiquitousKeyValueStore 的问题是你最多可以存储 1MB 的数据。

以上是关于我如何在 iCloud 中保存 NSData的主要内容,如果未能解决你的问题,请参考以下文章

如何在选择文档并使用 UIDocumentPickerViewController 下载到设备之前在 iCloud 中查找文档的大小

如何在不重新保存的情况下从 iCloud 下载图像?

在 icloud 钥匙串中保存密码

如何在 Swift 中从 NSData 显示 PDF - 如何将 PDF 保存到文档文件夹 Swift - 如何在 Swift 中通过 WebView 从保存的 NSData 显示 PDF

如何从 iCloud 打开 PDF

在 iCloud 上保存数据