我如何在 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
响应bytes
和length
,不就是一个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 中查找文档的大小
如何在 Swift 中从 NSData 显示 PDF - 如何将 PDF 保存到文档文件夹 Swift - 如何在 Swift 中通过 WebView 从保存的 NSData 显示 PDF