参考文章:
沙盒(sandbox)(官方文档 )
iOS沙盒主要包含以下三个文件夹:
获取沙盒路径
1 2 NSString *homeDir = NSHomeDirectory ();
注:每次编译代码会生成新的沙盒,注意是编译不是启动,所以模拟器或者真机运行你每次运行所得到的沙盒路径都是不一样,就是上面提到的标识符不一样,正式版app真机的话启动杀死,不会生成新的沙盒
1)、Documents
保存应用程序运行时生成的需要持久化数据,iTunes会自动备份该目录。 苹果公司建议将程序中建立的活在程序浏览到的文件数据保存在该目录下,iTunes备份和恢复的时候会包括此目录。
1 2 NSString *docPath = [NSSearchPathForDirectoriesInDomains (NSDocumentDirectory , NSUserDomainMask , YES ) lastObject];
2)、Library
存储程序的默认设置和其他状态信息,iTunes会自动备份该文件目录
Library/Caches:存放缓存文件,iTunes不会备份此目录,此目录下文件不会在应用退出时删除,通常存放体积比较大,但并不是很重要的资源
Library/Preferences:保存应用的所有偏好设置,iOS的Setting(设置)应用会在该目录中查找应用的设置信息,iTunes会自动备份该目录。 ——PS:如果你想对偏好设置进行相应的操作,应该使用NSUserDefaults类来取得和设置应用程序的偏好,而不是直接创建偏好设置文件。
包含两个文件夹
1 2 3 4 5 6 7 8 9 NSString *libDir = [NSSearchPathForDirectoriesInDomains (NSLibraryDirectory , NSUserDomainMask , YES ) lastObject];NSString *cachePath = [NSSearchPathForDirectoriesInDomains (NSCachesDirectory , NSUserDomainMask , YES ) lastObject];NSString *prePath = [NSSearchPathForDirectoriesInDomains (NSPreferencePanesDirectory , NSUserDomainMask , YES ) lastObject];
3)、tmp
保存应用程序运行时所需的临时数据,使用完毕后再将相应的文件从该目录删除,应用没有运行时,系统也有可能会清除该目录下的文件,iTunes不会同步该目录,你的iPhone重启时,该目录下的文件会被删除。
数据存储的几种方式 1)、property list(属性列表)
只能存储系统自带的数据类型,一般实际开发中存储字典、数组,自定义的模型无法进行存储。
1 2 3 4 5 6 7 8 9 #define kUserPath [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).firstObject stringByAppendingPathComponent:@"local.plist" ] NSMutableDictionary *dic = [NSMutableDictionary dictionary]; [dic setObject:@"小明" forKey:@"name" ]; [dic writeToFile:kUserPath atomically:YES ]; NSMutableDictionary *localDic = [[NSMutableDictionary alloc] initWithContentsOfFile:kUserPath]; NSLog (@"localDic = %@" ,localDic);
2)、Preference(偏好设置):NSUserDefaults
只能存储系统自带的数据类型,自定义的对象无法存储。 偏好设置好处: 1.不需要关心文件名(不需要设置路径) 2.键值对存储(账号相关信息) 对象存储 底层实现原理就是封装了一个字典
1 2 3 4 5 6 7 8 9 NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];[userDefaults setObject:@"123" forKey:@"account" ]; [userDefaults setObject:@"123456" forKey:@"pwd" ]; [userDefaults setBool:YES forKey:@"status" ]; [userDefaults synchronize];
3)、文件读写 3.1 简单对象写入文件 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 NSArray *array = NSSearchPathForDirectoriesInDomains (NSDocumentDirectory , NSUserDomainMask , YES ); NSString *docPathStr = [array lastObject]; NSString *strPath = [docPathStr stringByAppendingPathComponent:@"/text.txt" ]; NSString *contant = @"Hello, world!" ; [contant writeToFile:strPath atomically:YES encoding:NSUTF8StringEncoding error:nil ]; NSString *arrayPath = [docPathStr stringByAppendingString:@"/arry.txt" ]; NSArray *arr = @[ @"Jobs" , @"Cook" , @"Apple" ]; [arr writeToFile:arrayPath atomically:YES ]; NSString *dicPath = [docPathStr stringByAppendingString:@"/dic.txt" ]; NSDictionary *dic = @{ @"name" : @"Jobs" , @"sex" : @"男" }; [dic writeToFile:dicPath atomically:YES ]; UIImage *img = [UIImage imageNamed:@"avatar1" ]; NSString *dataPath = [docPathStr stringByAppendingPathComponent:@"data.txt" ]; NSData *data = UIImagePNGRepresentation (img); [data writeToFile:dataPath atomically:YES ]; #pragma mark - NSFileManager NSError *error; NSFileManager *manger = [NSFileManager defaultManager]; NSString *filePath = [docPathStr stringByAppendingString:@"/test1" ]; [manger createDirectoryAtPath:filePath withIntermediateDirectories:YES attributes:nil error:nil ]; NSString *filePath1 = [filePath stringByAppendingString:@"/test.png" ]; [manger createFileAtPath:filePath1 contents:data attributes:nil ]; NSString *filePath2 = [docPathStr stringByAppendingString:@"/test1/test2.png" ]; [manger copyItemAtPath:filePath1 toPath:filePath2 error:&error]; NSString *filePath3 = [docPathStr stringByAppendingString:@"/test2" ]; [manger createDirectoryAtPath:filePath3 withIntermediateDirectories:YES attributes:nil error:&error]; NSString *filePath4 = [filePath3 stringByAppendingString:@"/test4.png" ]; [manger moveItemAtPath:filePath1 toPath:filePath4 error:&error]; [manger removeItemAtPath:filePath4 error:&error]; BOOL isExist = [manger fileExistsAtPath:filePath4]; NSLog (@"isExist = %d" ,isExist); NSArray *fileArr = [manger subpathsOfDirectoryAtPath: docPathStr error:nil ]; NSLog (@"fileArr = %@" ,fileArr); NSArray *fileArr2 = [manger subpathsAtPath: docPathStr ]; NSLog (@"fileArr2 = %@" ,fileArr2);
3.2、NSKeyedArchiver(归档)+ 文件读写
该方式一般都是保存自定义对象的时候使用.因为plist文件不能够保存自定义对象. 如果一个字典当中保存有自定义对象,如果把这个字典写入到文件当中,它是不会生成plist文件的.
复杂对象写入文件的过程(复杂对象->归档->NSData->writeToFile)
从文件中读取出复杂对象过程(读取文件->NSData->反归档->复杂对象)
首先,复杂对象所属的类要遵守
其次,实现协议中的两个方法:
-(void)encodeWithCoder:(NSCoder *)aCoder; //序列化
-(id)initWithCoder:(NSCoder *)aDecoder; //反序列化
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 @interface UserModel : NSObject <NSCoding >@property (nonatomic , assign ) int ID;@property (nonatomic ,copy )NSString *name;@property (nonatomic ,copy )NSString *pwd;@property (nonatomic ,assign )int age;@end - (instancetype )initWithCoder:(NSCoder *)aDecoder{ self = [super init]; if (self ) { self .ID = [aDecoder decodeIntForKey:@"ID" ]; self .name = [aDecoder decodeObjectForKey:@"name" ]; self .pwd = [aDecoder decodeObjectForKey:@"pwd" ]; self .age = [aDecoder decodeIntForKey:@"age" ]; } return self ; } - (void )encodeWithCoder:(NSCoder *)aCoder{ [aCoder encodeInt:self .ID forKey:@"ID" ]; [aCoder encodeObject:self .name forKey:@"name" ]; [aCoder encodeObject:self .pwd forKey:@"pwd" ]; [aCoder encodeInt:self .age forKey:@"age" ]; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 UserModel *userModel = [[UserModel alloc] init]; userModel.ID = 10 ; userModel.name = @"Jobs" ; userModel.pwd = @"123456" ; userModel.age = 26 ; NSMutableData *data = [NSMutableData data];NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data];[archiver encodeObject:userModel forKey:@"user" ]; [archiver finishEncoding]; NSString *mulDataPath = [NSSearchPathForDirectoriesInDomains (NSDocumentDirectory , NSUserDomainMask , YES ) lastObject];NSString *dataPath = [mulDataPath stringByAppendingString:@"/archiver.plist" ];[data writeToFile:dataPath atomically:YES ]; NSData *readData = [NSData dataWithContentsOfFile:dataPath];NSKeyedUnarchiver *unAchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:readData];UserModel *localUser1 = [unAchiver decodeObjectForKey:@"user" ]; [unAchiver finishDecoding];
注:归档不是数据持久化手段,而是为文件读写做准备。文件读写才是数据持久化的方式。
Office等文件预览 方法一:UIDocumentInteractionController 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 - (void )readDocWithDucument1 { NSString *ducumentLocation = [[NSBundle mainBundle] pathForResource:docNameString ofType:docTypeString]; NSURL *url = [NSURL fileURLWithPath:ducumentLocation]; NSString *cachePath = [NSSearchPathForDirectoriesInDomains (NSCachesDirectory , NSUserDomainMask , YES ) lastObject]; cachePath = [cachePath stringByAppendingPathComponent:@"temp.docx" ]; NSURL *cacheUrl = [NSURL fileURLWithPath:cachePath]; NSFileManager *fileManger = [NSFileManager defaultManager]; NSError *error = nil ; [fileManger copyItemAtURL:url toURL:cacheUrl error:&error]; _documentInteractionController = [UIDocumentInteractionController interactionControllerWithURL:cacheUrl]; _documentInteractionController.delegate = self ; [_documentInteractionController presentOptionsMenuFromRect:CGRectZero inView:self .view animated:YES ]; } - (UIViewController *)documentInteractionControllerViewControllerForPreview:(UIDocumentInteractionController *)controller { return self ; } - (UIView *)documentInteractionControllerViewForPreview:(UIDocumentInteractionController *)controller { return self .view; } - (CGRect )documentInteractionControllerRectForPreview:(UIDocumentInteractionController *)controller { return self .view.bounds; }
方法二:QLPreviewController 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 - (void )quickLook { QLPreviewController *preVC = [[QLPreviewController alloc] init]; preVC.dataSource = self ; [self presentViewController:preVC animated:YES completion:nil ]; } #pragma mark - QLPreviewControllerDataSource 代理方法 - (NSInteger )numberOfPreviewItemsInPreviewController:(QLPreviewController *)controller { return 1 ; } - (id <QLPreviewItem>)previewController:(QLPreviewController *)controller previewItemAtIndex:(NSInteger )index { NSString *ducumentLocation = [[NSBundle mainBundle] pathForResource:docNameString ofType:docTypeString]; NSURL *url = [NSURL fileURLWithPath:ducumentLocation]; return url; }
方法三:UIWebView 1 2 3 4 5 6 7 8 9 10 11 12 13 14 - (void )readDocfile { NSString *ducumentLocation = [[NSBundle mainBundle] pathForResource:docNameString ofType:docTypeString]; NSURL *url = [NSURL fileURLWithPath:ducumentLocation]; UIWebView *webView = [[UIWebView alloc] initWithFrame:self .view.frame]; webView.delegate = self ; webView.multipleTouchEnabled = YES ; webView.scalesPageToFit = YES ; NSURLRequest *request = [NSURLRequest requestWithURL:url]; [webView loadRequest:request]; [self .view addSubview:webView]; }