应用沙盒简介
1、iOS系统为每个应用程序提供了独立的存储空间“沙盒”。
2、每个应用程序都遵守沙盒机制,即程序仅能访问自身所属沙盒空间内的数据。
3、沙盒为程序主路径,包含以下目录:
Document:存储用户自定义数据。
Library:存储应用程序相关数据。
tmp: 存放临时文件的地方,当iPhone重启时,会丢弃该目录里所有的文件 。
4、路径获取:
获取沙盒主路径:NSHomeDirectory()
获取Document路径:[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject]
获取Library路径:[NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES) lastObject]
获取Temp路径:NSTemporaryDirectory( )
获取应用包路径:[[NSBundle mainBundle] pathForAuxiliaryExecutable:@”“]
NSFileManager 文件管理类
1、NSFileManager可以完成沙盒路径下的文件管理工作,包括目录创建、文件创建、删除、移动、复制等。
2、NSFileManager使用单例方法访问:
+ (NSFileManager *)defaultManager;
3、判断指定路径下是否存在文件:
- (BOOL)fileExistsAtPath:(NSString *)path;
- (BOOL)fileExistsAtPath:(NSString *)path isDirectory:(BOOL *)isDirectory;
4、文件处理方法:
// 1、创建文件
- (BOOL)createFileAtPath:(NSString *)path contents:(NSData *)data attributes:(NSDictionary *)attr;
// 2、创建目录
- (BOOL)createDirectoryAtPath:(NSString *)path attributes:(NSDictionary *)attributes;
// 3、复制文件
- (BOOL)copyItemAtPath:(NSString *)srcPath toPath:(NSString *)dstPath error:(NSError **)error;
// 4、移动文件
- (BOOL)moveItemAtPath:(NSString *)srcPath toPath:(NSString *)dstPath error:(NSError **)error;
// 5、删除文件
- (BOOL)removeItemAtPath:(NSString *)path error:(NSError **)error;
NSUserDefaults
1、NSUserDefaults 可以让用户对应用程序进行一些简单的配置。
2、NSUserDefaults 同时也是一种轻量的持久化存储机制。
3、NSUserDefaults 使用单例方法访问:
+ (NSUserDefaults *)standardUserDefaults;
4、NSUserDefaults 存储数据:
- (void)setObject:(id)value forKey:(NSString *)defaultName;
- (void)setInteger:(NSInteger)value forKey:(NSString *)defaultName;
- (void)setFloat:(float)value forKey:(NSString *)defaultName;
- (void)setDouble:(double)value forKey:(NSString *)defaultName;
- (void)setBool:(BOOL)value forKey:(NSString *)defaultName;
- (void)setURL:(NSURL *)url forKey:(NSString *)defaultName;
5、NSUserDefaults 读取数据:
- (id)objectForKey:(NSString *)defaultName;
- (NSInteger)integerForKey:(NSString *)defaultName;
- (float)floatForKey:(NSString *)defaultName;
- (double)doubleForKey:(NSString *)defaultName;
- (BOOL)boolForKey:(NSString *)defaultName;
- (NSURL *)URLForKey:(NSString *)defaultName;
6、NSUserDefaults 同步数据到文件系统:
- (BOOL)synchronize;
属性列表
1、Cocoa中有一类名为属性列表的文件,简写为plist(Property List)。
2、Cocoa知道如何将此类对象进行保存和加载,即属性列表对象可以直接写入文件,或从文件加载为相应属性列表对象。
3、常见的属性列表数据类型包括:NSString、NSNumber、NSDate、NSData、NSArray、NSDictionary及其变体(NSMutable)。
4、对于集合属性列表类NSArray、NSDictionary需要其内部的对象也是属性列表类,才可以写入文件系统。
5、属性列表类写入文件系统方法:
- (BOOL)writeToFile:(NSString *)path atomically:(BOOL)useAuxiliaryFile;
6、Plist文件创建步骤:Command + N -> iOS or OSX -> Resource -> Peoperty List
对象归档
1、系统属性列表类默认可以写入文件,用户自定义类无法写入文件。
2、自定义类的对象可以通过归档来完成写入文件系统。
4、通过遵守NSCoding协议并实现协议方法:
- (void)encodeWithCoder:(NSCoder *)aCoder;
- (id)initWithCoder:(NSCoder *)aDecoder;
5、使用NSKeyedUnarchiver、NSKeyedArchiver将对象归档为NSData写入文件或加载到内存。
数据持久化案例
界面展示
代码示例
Plist代码示例
#import "ViewController.h"
/**< 打印路径 */
#define NSLOG_DOCUMENTS_PATH NSLog(@"%@", NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).firstObject);
/**< 沙盒地址 */
#define DOCUMENT_PATH NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).firstObject
/**< 文件管理类 */
#define DEFAULT_FILEMANAGER [NSFileManager defaultManager]
static NSString *const PlistName = @"/UserInfomation.plist";
static NSString *const NameKey = @"name";
static NSString *const AddressKey = @"address";
static NSString *const PhoneKey = @"phone";
@interface ViewController ()
@property (strong, nonatomic) IBOutlet UITextField *nameTextField;
@property (strong, nonatomic) IBOutlet UITextField *addressTextField;
@property (strong, nonatomic) IBOutlet UITextField *phoneTextField;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
}
#pragma mark *** Plist ***
/**
* 手动创建Plist文件
*
* 1、Command + N -》 ios or OSX -》Resource -》Property List
* 2、对plist文件数据的操作,如果增加一条数据,key相同则是对原有数据修改
*/
- (IBAction)plist_save:(id)sender {
if ([self isEmptyData]) {
NSLog(@"文本信息为空,存储失败!");
return;
}
// 获取plist路径
NSString *plistPath = [DOCUMENT_PATH stringByAppendingString:PlistName];
// 初始化根数组
NSMutableArray *rootArr = nil;
// 初始化文件管理器
NSFileManager *fileManager = DEFAULT_FILEMANAGER;
// 判断沙盒中是否存在属性列表,如果存在,则根据plist文件初始化根字典,如果不存在,则直接初始化根字典;
if ([fileManager fileExistsAtPath:plistPath]) {
rootArr = [NSMutableArray arrayWithContentsOfFile:plistPath];
}else {
rootArr = [NSMutableArray array];
}
// 初始化用户信息字典
NSMutableDictionary *infoDict = [NSMutableDictionary dictionary];
// 录入用户信息
[infoDict setObject:self.nameTextField.text forKey:NameKey];
[infoDict setObject:self.addressTextField.text forKey:AddressKey];
[infoDict setObject:self.phoneTextField.text forKey:PhoneKey];
// 将用户新字典存入数组
[rootArr addObject:infoDict];
// 将根输入写入沙盒路径
if ([rootArr writeToFile:plistPath atomically:YES]) {
NSLog(@"属性列表添加数据成功!");
}else {
NSLog(@"属性列表添加数据失败!");
}
}
- (IBAction)plist_read:(id)sender {
NSString *plistPath = [DOCUMENT_PATH stringByAppendingString:PlistName];
if ([DEFAULT_FILEMANAGER fileExistsAtPath:plistPath]) {
NSArray *rootArr = [NSArray arrayWithContentsOfFile:plistPath];
if (rootArr.count > 0) {
NSLog(@"%@", rootArr);
}else {
NSLog(@"属性列表中没有数据!");
}
}else {
NSLog(@"属性列表不存在!");
}
}
- (IBAction)plist_delete:(id)sender {
NSString *plistPath = [DOCUMENT_PATH stringByAppendingString:PlistName];
if ([DEFAULT_FILEMANAGER fileExistsAtPath:plistPath]) {
NSMutableArray *rootArr = [NSMutableArray arrayWithContentsOfFile:plistPath];
if (rootArr.count > 0) {
[rootArr removeAllObjects];
[rootArr writeToFile:plistPath atomically:YES];
NSLog(@"属性列表删除数据成功!");
}else {
NSLog(@"属性列表中没有数据!");
}
}else {
NSLog(@"属性列表不存在!");
}
}
#pragma mark *** 异常处理 ***
- (BOOL)isEmptyData {
// 判断文本是否为空
if (self.nameTextField.text.length == 0 || self.addressTextField.text.length == 0 || self.phoneTextField.text.length == 0) {
return YES;
}else {
return NO;
}
}
#pragma mark *** Touches ***
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
[self.view endEditing:YES];
}
@end
NSUserDefaults代码示例
#import "ViewController.h"
static NSString *const DefaultsKey = @"data";
static NSString *const NameKey = @"name";
static NSString *const AddressKey = @"address";
static NSString *const PhoneKey = @"phone";
@interface ViewController ()
@property (strong, nonatomic) IBOutlet UITextField *nameTextField;
@property (strong, nonatomic) IBOutlet UITextField *addressTextField;
@property (strong, nonatomic) IBOutlet UITextField *phoneTextField;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
}
#pragma mark *** NSUserDefaults ***
- (IBAction)defaults_save:(id)sender {
if ([self isEmptyData]) {
NSLog(@"文本信息为空,存储失败!");
return;
}
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSMutableArray *rootArr = nil;
if ([defaults objectForKey:DefaultsKey]) {
rootArr = [NSMutableArray arrayWithArray:[defaults objectForKey:DefaultsKey]];
}else {
rootArr = [NSMutableArray array];
}
NSDictionary *infoDict = @{NameKey : self.nameTextField.text,
AddressKey: self.addressTextField.text,
PhoneKey : self.phoneTextField.text};
[rootArr addObject:infoDict];
[defaults setObject:rootArr forKey:DefaultsKey];
[defaults synchronize];
NSLog(@"系统单例存储数据成功!");
}
- (IBAction)defaults_read:(id)sender {
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSArray *rootArr = [defaults objectForKey:DefaultsKey];
if (rootArr && rootArr.count > 0) {
NSLog(@"%@", rootArr);
}else {
NSLog(@"系统单例读取数据失败!");
}
}
- (IBAction)defaults_delete:(id)sender {
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults removeObjectForKey:DefaultsKey];
[defaults synchronize];
NSLog(@"系统单例删除数据成功!");
}
#pragma mark *** 异常处理 ***
- (BOOL)isEmptyData {
// 判断文本是否为空
if (self.nameTextField.text.length == 0 || self.addressTextField.text.length == 0 || self.phoneTextField.text.length == 0) {
return YES;
}else {
return NO;
}
}
#pragma mark *** Touches ***
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
[self.view endEditing:YES];
}
@end
Archive对象归档代码示例
- 自定类归档需遵守NSCoding协议,此处对Person类进行归档。
steps 1 -> Person.h文件
#import <Foundation/Foundation.h>
@interface Person : NSObject <NSCoding>
@property (nonatomic, strong)NSString *name;
@property (nonatomic, strong)NSString *address;
@property (nonatomic, strong)NSString *phoneNumber;
- (NSString *)description;
@end
steps 2 -> Person.m文件
#import "Person.h"
@implementation Person
// - 当将一个自定义对象保存到文件的时候就会调用该方法;
// - 在该方法中,说明如何存储自定义对象的属性,也就是说在该方法中说清楚存储自定义对象的哪些属性;
- (void)encodeWithCoder:(NSCoder *)aCoder {
[aCoder encodeObject:self.name forKey:@"name"];
[aCoder encodeObject:self.address forKey:@"address"];
[aCoder encodeObject:self.phone forKey:@"phone"];
}
// - 当文件中读取一个对象的时候就会调用该方法;
// - 在该方法中说明如何读取保存在文件中的对象,也就是说在该方法中说清楚怎么读取文件中的对象
- (instancetype)initWithCoder:(NSCoder *)aDecoder {
if (self = [super init]) {
self.name = [aDecoder decodeObjectForKey:@"name"];
self.address = [aDecoder decodeObjectForKey:@"address"];
self.phone = [aDecoder decodeObjectForKey:@"phone"];
}
return self;
}
- (NSString *)description {
return [NSString stringWithFormat:@"\nname = %@\naddress = %@\nphone = %@",
self.name,
self.address,
self.phone];
}
@end
steps 3 -> ViewController.m文件
#import "ViewController.h"
#import "Person.h"
/**< 打印路径 */
#define NSLOG_DOCUMENTS_PATH NSLog(@"%@", NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).firstObject);
/**< 沙盒地址 */
#define DOCUMENT_PATH NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).firstObject
/**< 文件管理类 */
#define DEFAULT_FILEMANAGER [NSFileManager defaultManager]
static NSString *const ArchiveName = @"/PersonInfomation";
@interface ViewController ()
@property (strong, nonatomic) IBOutlet UITextField *nameTextField;
@property (strong, nonatomic) IBOutlet UITextField *addressTextField;
@property (strong, nonatomic) IBOutlet UITextField *phoneTextField;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
}
#pragma mark *** Archive ***
/**
* 归档:直接把一个对象弄成一个文件
* 遵循<NSCoding>的类的对象都可以被归档
* 自定义类若想归档需遵守<NSCoding>协议
* 归档方法: + (BOOL)archiveRootObject:(id)rootObject toFile:(NSString *)path;
*
*/
- (IBAction)archive_save:(id)sender {
if ([self isEmptyData]) {
NSLog(@"文本信息为空,存储失败!");
return;
}
// 创建对象
Person *person = [[Person alloc] init];
// 对象赋值
person.name = self.nameTextField.text;
person.address = self.addressTextField.text;
person.phone = self.phoneTextField.text;
// 获取归档路径
NSString *archivePath = [DOCUMENT_PATH stringByAppendingString:ArchiveName];
// 将自定义对象保存到文件中
if ([NSKeyedArchiver archiveRootObject:person toFile:archivePath]) {
NSLog(@"归档数据成功!");
}else {
NSLog(@"归档数据失败!");
}
}
- (IBAction)archive_read:(id)sender {
NSString *archivePath = [DOCUMENT_PATH stringByAppendingString:ArchiveName];
Person *person = [NSKeyedUnarchiver unarchiveObjectWithFile:archivePath];
if (person) {
NSLog(@"%@", person);
}else {
NSLog(@"读取归档数据失败!");
}
}
- (IBAction)archive_delete:(id)sender {
NSString *archivePath = [DOCUMENT_PATH stringByAppendingString:ArchiveName];
if ([DEFAULT_FILEMANAGER fileExistsAtPath:archivePath]) {
[DEFAULT_FILEMANAGER removeItemAtPath:archivePath error:nil];
NSLog(@"删除归档成功!");
}else {
NSLog(@"归档文件不存在!");
}
}
#pragma mark *** 异常处理 ***
- (BOOL)isEmptyData {
// 判断文本是否为空
if (self.nameTextField.text.length == 0 || self.addressTextField.text.length == 0 || self.phoneTextField.text.length == 0) {
return YES;
}else {
return NO;
}
}
#pragma mark *** Touches ***
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
[self.view endEditing:YES];
}
@end