1. 沙盒机制
数据持久化的原因及本质: 存储在内存中的数据,程序关闭,内存释放,数据丢失,这种数据是临时的.数据持久化是将数据保存成文件,存储到程序的沙盒中.
每个应用程序都有独立的沙盒,就是一个文件夹,名字是随机分配的.每次打开的文件夹路径都不一样.
//
打印沙盒中文件夹的路径
- ( void )path
{
- ( void )path
{
//
每运行一次
相当于从新安装一次
重新安装就从新分配一个沙盒的路径
所以每次运行
路径都不一样
// NSDocumentationDirectory 要打印的文件夹地址
// NSUserDomainMask 搜索的范围
/*
NSUserDomainMask = 1, // user's home directory 用户目录中
NSLocalDomainMask = 2, // local to the current machine --- 当前机器中
NSNetworkDomainMask = 4, // publically available location in the local area network --- 网络课件的主机中
NSSystemDomainMask = 8, // provided by Apple, unmodifiable (/System)--- 系统目录 不可修改
NSAllDomainsMask = 0x0ffff // all domains: 所有的
*/
// 返回值是数组
/*
lastobject firstObject [0] 访问该数组都行
*/
1. document
路径
/*
该文件夹 一般存储用户的一些数据
*/
NSArray *array = NSSearchPathForDirectoriesInDomains ( NSDocumentDirectory , NSUserDomainMask , YES );
NSString *document = [array firstObject ];
NSLog ( @"%@" , document);
该文件夹 一般存储用户的一些数据
*/
NSArray *array = NSSearchPathForDirectoriesInDomains ( NSDocumentDirectory , NSUserDomainMask , YES );
NSString *document = [array firstObject ];
NSLog ( @"%@" , document);
2.
缓存文件夹路径
//
该文件夹
一般存储缓存文件
NSArray *array1 = NSSearchPathForDirectoriesInDomains ( NSCachesDirectory , NSUserDomainMask , YES );
NSString *cache = [array1 lastObject ];
NSLog ( @"%@" , cache);
NSArray *array1 = NSSearchPathForDirectoriesInDomains ( NSCachesDirectory , NSUserDomainMask , YES );
NSString *cache = [array1 lastObject ];
NSLog ( @"%@" , cache);
3.tmp
文件夹路径
//
该文件夹
一般存储
tmp
文件
NSString *tmp = NSTemporaryDirectory();
NSLog(@"%@", tmp);
4.
打印沙盒的主目录
路径
NSString *home = NSHomeDirectory ();
NSLog ( @"%@" , home);
}
2. 简单对象写入文件
//
简单对象
写入文件
/**
* 1. 拼接要写入的路径 ( 要注意的 : 路径一定要拼对 )
2. 调用写入方法
3. 注意 : 如果写入简单对象字典或者数组 那么数组字典中存储的数据 必须是简单对象 无法写入复杂对象
*/
- ( void )writeFile
{
// 简单对象 ( 字符串 字典 数组 data...... 这些系统写好的简单对象 )
// 写入文件的路径 < 在 documents 路径下写入一个叫 /xiaoshuo.txt 的文件 >
NSArray *array = NSSearchPathForDirectoriesInDomains ( NSDocumentDirectory , NSUserDomainMask , YES );
NSString *documentsPath = [array lastObject ];
// 拼接要写入的文件的路径 // stringByAppendingPathCommponent
NSString *path = [ NSString stringWithFormat : @"%@/xiaoshuo.txt" , documentsPath];
NSLog ( @"%@" , path);
NSString *string = @" 第一章 , 在一个夜黑风高的早上 , 我漫步在 ... ..." ;
// 写入的方法
// atomically 如果 yes 在写入的过程中 如果出现程序崩溃 就不应写写入
[string writeToFile :path atomically : YES encoding : NSUTF8StringEncoding error : nil ];
// 写入一个数组
// 必须给后缀 默认是 txt 的
NSString *path1 = [documentsPath stringByAppendingPathComponent : @"array.plist" ];
NSArray *array1 = @[ @"1" , @"2" , @"3" , @"4" , @"5" ] ;
[array1 writeToFile :path1 atomically : YES ];
// 写入一个字典
NSString *dicPath = [documentsPath stringByAppendingPathComponent : @"dic.txt" ];
NSDictionary *dic = [ NSDictionary dictionaryWithObjectsAndKeys : @"A" , @"a" , @"B" , @"b" , @"C" , @"c" , @"D" , @"d" , nil ];
[dic writeToFile :dicPath atomically : YES ];
// 写入一个 data
// data 的后缀名是 .da
NSString *dataPath = [documentsPath stringByAppendingPathComponent : @"data.da" ];
NSData *data = [string dataUsingEncoding : NSUTF8StringEncoding ];
[data writeToFile :dataPath atomically : YES ];
// 复杂对象 ( 自定义的类创建的对象 Person 类 ,Students 类 )
}
// 读取写入的文件
- ( void )readingFile
{
// 读字符串
// 获取路径
NSArray *array = NSSearchPathForDirectoriesInDomains ( NSDocumentDirectory , NSUserDomainMask , YES );
NSString *documentsPath = [array lastObject ];
// 拼接要写入的文件的路径 // stringByAppendingPathCommponent
NSString *path = [ NSString stringWithFormat : @"%@/xiaoshuo.txt" , documentsPath];
NSString *string = [[ NSString alloc ] initWithContentsOfFile :path encoding : NSUTF8StringEncoding error : nil ];
NSLog ( @"%@" , string);
// 读取数组
NSString *path1 = [documentsPath stringByAppendingPathComponent : @"array.plist" ];
NSArray *array2 = [[ NSArray alloc ] initWithContentsOfFile :path1];
NSLog ( @"%@" , array2);
// 读取字典
NSString *dicPath = [documentsPath stringByAppendingPathComponent : @"dic.plist" ];
NSDictionary *dic1 = [[ NSDictionary alloc ] initWithContentsOfFile :dicPath];
NSLog ( @"%@" , dic1);
// 读取 data
NSString *dataPath = [documentsPath stringByAppendingPathComponent : @"data.da" ];
NSData *data1 =[[ NSData alloc ] initWithContentsOfFile :dataPath];
NSString *strings = [[ NSString alloc ] initWithData :data1 encoding : NSUTF8StringEncoding ];
/**
* 1. 拼接要写入的路径 ( 要注意的 : 路径一定要拼对 )
2. 调用写入方法
3. 注意 : 如果写入简单对象字典或者数组 那么数组字典中存储的数据 必须是简单对象 无法写入复杂对象
*/
- ( void )writeFile
{
// 简单对象 ( 字符串 字典 数组 data...... 这些系统写好的简单对象 )
// 写入文件的路径 < 在 documents 路径下写入一个叫 /xiaoshuo.txt 的文件 >
NSArray *array = NSSearchPathForDirectoriesInDomains ( NSDocumentDirectory , NSUserDomainMask , YES );
NSString *documentsPath = [array lastObject ];
// 拼接要写入的文件的路径 // stringByAppendingPathCommponent
NSString *path = [ NSString stringWithFormat : @"%@/xiaoshuo.txt" , documentsPath];
NSLog ( @"%@" , path);
NSString *string = @" 第一章 , 在一个夜黑风高的早上 , 我漫步在 ... ..." ;
// 写入的方法
// atomically 如果 yes 在写入的过程中 如果出现程序崩溃 就不应写写入
[string writeToFile :path atomically : YES encoding : NSUTF8StringEncoding error : nil ];
// 写入一个数组
// 必须给后缀 默认是 txt 的
NSString *path1 = [documentsPath stringByAppendingPathComponent : @"array.plist" ];
NSArray *array1 = @[ @"1" , @"2" , @"3" , @"4" , @"5" ] ;
[array1 writeToFile :path1 atomically : YES ];
// 写入一个字典
NSString *dicPath = [documentsPath stringByAppendingPathComponent : @"dic.txt" ];
NSDictionary *dic = [ NSDictionary dictionaryWithObjectsAndKeys : @"A" , @"a" , @"B" , @"b" , @"C" , @"c" , @"D" , @"d" , nil ];
[dic writeToFile :dicPath atomically : YES ];
// 写入一个 data
// data 的后缀名是 .da
NSString *dataPath = [documentsPath stringByAppendingPathComponent : @"data.da" ];
NSData *data = [string dataUsingEncoding : NSUTF8StringEncoding ];
[data writeToFile :dataPath atomically : YES ];
// 复杂对象 ( 自定义的类创建的对象 Person 类 ,Students 类 )
}
// 读取写入的文件
- ( void )readingFile
{
// 读字符串
// 获取路径
NSArray *array = NSSearchPathForDirectoriesInDomains ( NSDocumentDirectory , NSUserDomainMask , YES );
NSString *documentsPath = [array lastObject ];
// 拼接要写入的文件的路径 // stringByAppendingPathCommponent
NSString *path = [ NSString stringWithFormat : @"%@/xiaoshuo.txt" , documentsPath];
NSString *string = [[ NSString alloc ] initWithContentsOfFile :path encoding : NSUTF8StringEncoding error : nil ];
NSLog ( @"%@" , string);
// 读取数组
NSString *path1 = [documentsPath stringByAppendingPathComponent : @"array.plist" ];
NSArray *array2 = [[ NSArray alloc ] initWithContentsOfFile :path1];
NSLog ( @"%@" , array2);
// 读取字典
NSString *dicPath = [documentsPath stringByAppendingPathComponent : @"dic.plist" ];
NSDictionary *dic1 = [[ NSDictionary alloc ] initWithContentsOfFile :dicPath];
NSLog ( @"%@" , dic1);
// 读取 data
NSString *dataPath = [documentsPath stringByAppendingPathComponent : @"data.da" ];
NSData *data1 =[[ NSData alloc ] initWithContentsOfFile :dataPath];
NSString *strings = [[ NSString alloc ] initWithData :data1 encoding : NSUTF8StringEncoding ];
NSLog(@"%@", strings);
}
3. NSFileMange
// 创建一个文件夹
- ( void )creatFile
{
// 需求 在 documents 文件夹先创建一个 download 文件夹
//NSArray *array = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsPath = kDocumentsPath ;
// 拼接路径
NSString *downloadPath = [documentsPath stringByAppendingPathComponent : @"Download" ];
// 创建文件夹
/*
文件管理者这个类是个单例类 用来对文件进行操作
*/
NSFileManager *fileManager = [ NSFileManager defaultManager ];
/*
withIntermediateDirectories 如果是 YES 情况下 要创建的话 存在的话 可以进行覆盖 反之文件存在的话不能对齐进行覆盖 然后创建失败
attributes 设置一些属性 ( 只读 .....)
*/
/**
* /Users/lanou3g/Library/Developer/CoreSimulator/Devices/F4C0035C-BFC9-4B9A-95D1-59CE94B63E35/data/Containers/Data/Application/8A4CBE00-1C0D-4E03-893E-B389A42397DE/Documents/Download
*/
BOOL isCreatFile = [fileManager createDirectoryAtPath :downloadPath withIntermediateDirectories : YES attributes : nil error : nil ];
NSLog ( @"%d" , isCreatFile);
}
// 移动文件夹
/*
移动需要俩路径
*/
- ( void )moveFile
{
// 获取原来的路径
NSString *oldPath = [ kDocumentsPath stringByAppendingPathComponent : @"Download" ];
// 获取新路径 library 下的 cache 文件夹
NSString *cachesPath = [ kCachesPath stringByAppendingPathComponent : @"Download" ];
// 创建 文件管理者的对象
NSFileManager *fileManager1 = [ NSFileManager defaultManager ];
// 移动文件夹
BOOL isMoveFile = [fileManager1 moveItemAtPath :oldPath toPath :cachesPath error : nil ];
NSLog ( @"%d" , isMoveFile);
}
// 复制文件夹
- ( void )copyFile
{
// 获取新路径 library 下的 cache 文件夹 复制到 documents 文件夹下
NSString *Path = [ kCachesPath stringByAppendingPathComponent : @"Download" ];
// 获取需要复制的路径
NSString *Path1 = [ kDocumentsPath stringByAppendingPathComponent : @"Download" ];
// 创建一个新的文件管理者对象
NSFileManager *fileManger2 = [ NSFileManager defaultManager ];
// 复制文件夹
BOOL isCopyFile = [fileManger2 copyItemAtPath :Path toPath :Path1 error : nil ];
NSLog ( @"%d" , isCopyFile);
}
// 删除文件夹
- ( void )removeFile
{
// 获取要删除的文件夹的路径
NSString *Path1 = [ kDocumentsPath stringByAppendingPathComponent : @"Download" ];
// 创建一个文件管理者的对象
NSFileManager *fileManger3 = [ NSFileManager defaultManager ];
// 删除文件夹
BOOL isRemoveFile = [fileManger3 removeItemAtPath :Path1 error : nil ];
NSLog ( @"%d" , isRemoveFile);
}
// 判断一个文件夹是否存在 ( 经常使用 )
- ( void )isExistFile
{
// 获取要判断的路径
NSString *Path = [ kCachesPath stringByAppendingPathComponent : @"Download" ];
// 创建文件管理者对象
NSFileManager *fileManage = [ NSFileManager defaultManager ];
// 判断是否存在
BOOL isExistFile = [fileManage isExecutableFileAtPath :Path];
NSLog ( @"%d" , isExistFile);
}
4. 复杂对象的归档
1) 对象类中的归档
.h
/**
* 复杂对象进行持久化 需要遵守一个协议 <NSCoding>
1.
*/
@interface JJModel : NSObject < NSCoding >
@property ( nonatomic , retain ) NSString *name;
@property ( nonatomic , assign ) NSInteger age;
@property ( nonatomic , retain ) NSData *data;
@end
.m
@implementation
JJModel
- ( void )dealloc
{
[ _data release ];
[ _name release ];
[ super dealloc ];
}
/**
* 对复杂对象进行持久化 叫做归档与反归档 ( 即 编码与解码 )
* 1. encodeWithCoder 归档方法
归档即 编码成可以进行持久化的格式
*
*/
- ( void )encodeWithCoder:( NSCoder *)aCoder
{
// 对每一个属性都要进行重新编码
// 注意属性的类型
// 除了对象类型 其他类型都有 特殊的编码方法
NSLog ( @"model 类中的编码 " );
[aCoder encodeObject : self . name forKey : @"name" ];
[aCoder encodeInteger : self . age forKey : @"age" ];
[aCoder encodeObject : self . data forKey : @"data" ];
}
- ( id )initWithCoder:( NSCoder *)aDecoder
{
self = [ super init ];
if ( self ) {
/**
* 解码的过程 跟编码一样 除了类型以外 也是有 特殊解码方法
注意 : 编码的时候给的 key 和解码的时候给的 key 是一样的
*/
NSLog ( @"model 类中的解码 " );
self . name = [aDecoder decodeObjectForKey : @"name" ];
self . age = [aDecoder decodeIntegerForKey : @"age" ];
self . data = [aDecoder decodeObjectForKey : @"data" ];
}
return self ;
}
- ( void )dealloc
{
[ _data release ];
[ _name release ];
[ super dealloc ];
}
/**
* 对复杂对象进行持久化 叫做归档与反归档 ( 即 编码与解码 )
* 1. encodeWithCoder 归档方法
归档即 编码成可以进行持久化的格式
*
*/
- ( void )encodeWithCoder:( NSCoder *)aCoder
{
// 对每一个属性都要进行重新编码
// 注意属性的类型
// 除了对象类型 其他类型都有 特殊的编码方法
NSLog ( @"model 类中的编码 " );
[aCoder encodeObject : self . name forKey : @"name" ];
[aCoder encodeInteger : self . age forKey : @"age" ];
[aCoder encodeObject : self . data forKey : @"data" ];
}
- ( id )initWithCoder:( NSCoder *)aDecoder
{
self = [ super init ];
if ( self ) {
/**
* 解码的过程 跟编码一样 除了类型以外 也是有 特殊解码方法
注意 : 编码的时候给的 key 和解码的时候给的 key 是一样的
*/
NSLog ( @"model 类中的解码 " );
self . name = [aDecoder decodeObjectForKey : @"name" ];
self . age = [aDecoder decodeIntegerForKey : @"age" ];
self . data = [aDecoder decodeObjectForKey : @"data" ];
}
return self ;
}
@end
//
归档复杂对象
- ( void )archiver
{
// 初始化要归档的对象
JJModel *model = [[ JJModel alloc ] init ];
// 赋值对象
model. name = @"JJ" ;
model. age = 60 ;
// 比如搞一个图片作为 data
UIImage *image = [ UIImage imageNamed : @"123" ];
model. data = UIImagePNGRepresentation (image);
// 创建一个可变的 data 进行初始化归档对象
NSMutableData *modelData = [ NSMutableData data ];
// 创建一个归档对象
NSKeyedArchiver *archiver = [[ NSKeyedArchiver alloc ] initForWritingWithMutableData :modelData];
NSLog ( @" 归档前 " );
// 进行归档编码
[archiver encodeObject :model forKey : @"JJmodel" ];
NSLog ( @" 归档后 " );
// 编码完成
[archiver finishEncoding ];
// 实际上归档 相当于把编码完的对象 保存到 data 中
// NSLog(@"%@", modelData);
// 把存有复杂对象的 data 写入文件 持久化
/**
* 1. 路径
*
* 2. 调写入的方法
*/
NSLog ( @"%@" , kDocumentsPath );
NSLog ( @" 存入文件夹 " );
NSString *modelDataPath = [ kDocumentsPath stringByAppendingPathComponent : @"JJModel.da" ];
[modelData writeToFile :modelDataPath atomically : YES ];
[archiver release ];
[model release ];
}
// 反归档 ( 解码的过程 )
- ( void )unArchiver
{
// 获取刚才归档的 data
NSString *modelDataPath = [ kDocumentsPath stringByAppendingPathComponent : @"JJModel.da" ];
NSData *data = [ NSData dataWithContentsOfFile :modelDataPath];
NSLog ( @"%@" , kDocumentsPath );
// 创建反归档的对象
NSKeyedUnarchiver *unAchiver = [[ NSKeyedUnarchiver alloc ] initForReadingWithData :data];
// 解码 返回一个对象
NSLog ( @" 解码前 " );
JJModel *model = [unAchiver decodeObjectForKey : @"JJmodel" ];
NSLog ( @" 解码后 " );
// 反归档完成
[unAchiver finishDecoding ];
// 释放对象
[unAchiver release ];
NSLog ( @"%@" , model. name );
UIImage *image = [ UIImage imageWithData :model. data ];
UIImageView *imageView = [[ UIImageView alloc ] initWithImage :image];
imageView. frame = CGRectMake ( 0 , 0 , 375 , 667 );
[ self . view addSubview :imageView];
- ( void )archiver
{
// 初始化要归档的对象
JJModel *model = [[ JJModel alloc ] init ];
// 赋值对象
model. name = @"JJ" ;
model. age = 60 ;
// 比如搞一个图片作为 data
UIImage *image = [ UIImage imageNamed : @"123" ];
model. data = UIImagePNGRepresentation (image);
// 创建一个可变的 data 进行初始化归档对象
NSMutableData *modelData = [ NSMutableData data ];
// 创建一个归档对象
NSKeyedArchiver *archiver = [[ NSKeyedArchiver alloc ] initForWritingWithMutableData :modelData];
NSLog ( @" 归档前 " );
// 进行归档编码
[archiver encodeObject :model forKey : @"JJmodel" ];
NSLog ( @" 归档后 " );
// 编码完成
[archiver finishEncoding ];
// 实际上归档 相当于把编码完的对象 保存到 data 中
// NSLog(@"%@", modelData);
// 把存有复杂对象的 data 写入文件 持久化
/**
* 1. 路径
*
* 2. 调写入的方法
*/
NSLog ( @"%@" , kDocumentsPath );
NSLog ( @" 存入文件夹 " );
NSString *modelDataPath = [ kDocumentsPath stringByAppendingPathComponent : @"JJModel.da" ];
[modelData writeToFile :modelDataPath atomically : YES ];
[archiver release ];
[model release ];
}
// 反归档 ( 解码的过程 )
- ( void )unArchiver
{
// 获取刚才归档的 data
NSString *modelDataPath = [ kDocumentsPath stringByAppendingPathComponent : @"JJModel.da" ];
NSData *data = [ NSData dataWithContentsOfFile :modelDataPath];
NSLog ( @"%@" , kDocumentsPath );
// 创建反归档的对象
NSKeyedUnarchiver *unAchiver = [[ NSKeyedUnarchiver alloc ] initForReadingWithData :data];
// 解码 返回一个对象
NSLog ( @" 解码前 " );
JJModel *model = [unAchiver decodeObjectForKey : @"JJmodel" ];
NSLog ( @" 解码后 " );
// 反归档完成
[unAchiver finishDecoding ];
// 释放对象
[unAchiver release ];
NSLog ( @"%@" , model. name );
UIImage *image = [ UIImage imageWithData :model. data ];
UIImageView *imageView = [[ UIImageView alloc ] initWithImage :image];
imageView. frame = CGRectMake ( 0 , 0 , 375 , 667 );
[ self . view addSubview :imageView];
}
5. 拓展,
UIAlertView 三秒钟后自己消失 调用一个方法
UIAlertView *alert = [[UIAlertView alloc]initWithTitle:@"
提示
"
message
:
@"
收藏成功
"
delegate
:
self
cancelButtonTitle
:
nil
otherButtonTitles
:
nil
,
nil
];
[alert
show
];
[ self performSelector : @selector (action:) withObject :alert afterDelay : 0.3 ];
[alert release ];
[ self performSelector : @selector (action:) withObject :alert afterDelay : 0.3 ];
[alert release ];
- (
void
)action:(
UIAlertView
*)alert
{
[alert dismissWithClickedButtonIndex : 0 animated : YES ];
{
[alert dismissWithClickedButtonIndex : 0 animated : YES ];
}