大纲
一、文件管理器
项目:FileManager0412
NSFileManager:文件管理器(单例类)
作用:管理文件/文件夹
(一)获取路径
1.获取home文件夹
2.获取Documents文件夹(拼接字符串)
3.获取指定文件路径(拼接字符串)
(二)文件文件夹的 创建/拷贝/移动/删除/属性
1.获取文件管理器
2.处理路径
3.管理器调用方法(创建/拷贝/移动/删除/属性)
二、多行选择
项目:SelectMutableLine0412
程序再次运行时读取数据:
1.创建基本表
2.处理单元格的 选中/取消选中
2.1 判断点击的Cell索引是否在_selectedRowArr中:
①在,取消选中
换图片 取消选中
移除 索引
②不在,选中
换图片 选中
添加 索引
3.数据存储(通知)
程序将要终止运行时,发出通知,存储数据
4.数据读取
程序再次运行时,从沙盒中取出数据
三、对象序列化
项目:ObjectSerialization0412
NSUserDefaults/writeToFile不能直接存储自定义类
结论:
数组/字典/字符串/NSData可以直接使用NSUserDefaults/writeToFile的方式将数据写入沙盒,因为这些类都实现了NSCoding协议
将自定义类对象写入沙盒的条件:
1.实现NSCoding协议
2.对象序列化
(一)序列化 方法1
序列化:
NSKeyedArchiver:编码器
作用:将一个实现NSCoding协议的对象转换为二进制数据(NSData)
1.编码
2.写入沙盒
反序列化:
NSKeyedUnarchiver:解码器
1.读取数据
2.解码
(二)方法2
序列化:
1.创建容器NSMutableData,保存要编码的对象
2.创建序列化器,指定要编码的对象容器
3.编码
4.结束编码
5.写入文件
反序列化:
1.读取数据
2.创建编码器
3.解码
4.结束解码
四、对容器类的拷贝
项目:FullyCopy0412
完全拷贝
方法1:
initWithArray:copyItems:对数组中的每一个元素调用 copy方法
条件:
1.元素实现 NSCoping 协议
2.元素是可变对象
方法2:序列化
条件:数组/元素 必须实现 NSCoding 协议
正文
一、文件管理器
项目:FileManager0412
NSFileManager:文件管理器(单例类)
作用:管理文件/文件夹
(一)获取路径
1.获取home文件夹
NSString *homeDirectoryPath = NSHomeDirectory();
2.获取Documents文件夹(拼接字符串)
NSString *docPath = [homeDirectoryPath stringByAppendingPathComponent:@"Documents"];
3.获取指定文件路径(拼接字符串)
NSString *filePath = [docPath stringByAppendingPathComponent:fileName];
(二)文件文件夹的 创建/拷贝/移动/删除/属性
1.获取文件管理器
2.处理路径
3.管理器调用方法(创建/拷贝/移动/删除/属性)
创建
[fileManager createFileAtPath:path contents:[@"123" dataUsingEncoding:NSUTF8StringEncoding] attributes:nil];
[fileManager createDirectoryAtPath:path withIntermediateDirectories:YES attributes:nil error:&error];
拷贝/移动
[fileManager copyItemAtPath:path1 toPath:path2 error:&error];
[fileManager moveItemAtPath:path1 toPath:path2 error:&error];
删除
[fileManager removeItemAtPath:path error:&error];
属性
NSDictionary *dic = [fileManager attributesOfItemAtPath:path error:&error];
源码:
@implementation ViewController
#pragma mark - **************** 获取文件路径
- (NSString *)getFilePath:(NSString *)fileName
{
NSString *homeDirectoryPath = NSHomeDirectory();
NSLog(@"%@",homeDirectoryPath);
NSString *docPath = [homeDirectoryPath stringByAppendingPathComponent:@"Documents"];
NSString *filePath = [docPath stringByAppendingPathComponent:fileName];
return filePath;
}
#pragma mark - **************** 创建文件
- (IBAction)createFile:(UIButton *)sender
{
//NSFileManager:文件管理器(单例类)
//用于管理文件/文件夹
//1.获取文件管理器
NSFileManager *fileManager = [NSFileManager defaultManager];
//2.获取路径
NSString *filePath = [self getFilePath:@"a.plist"];
BOOL isExists = [fileManager fileExistsAtPath:filePath];
if (isExists)
{
NSLog(@"该路径下存在该文件。");
}
else
{
NSLog(@"不存在,创建");
//3.创建文件
//AtPath:在哪个路径下创建
//contents:添加文件内容
//attributes:文件属性,nil表示默认属性
[fileManager createFileAtPath:filePath contents:[@"123" dataUsingEncoding:NSUTF8StringEncoding] attributes:nil];
}
}
#pragma mark - **************** 创建文件夹
- (IBAction)createDirectory:(UIButton *)sender
{
//1.获取文件管理器
NSFileManager *fileManager = [NSFileManager defaultManager];
//2.获取路径
NSString *directoryPath = [self getFilePath:@"class/student"];
BOOL isExists = [fileManager fileExistsAtPath:directoryPath];
if (isExists)
{
NSLog(@"该路径下存在该文件。");
}
else
{
NSLog(@"不存在,创建");
//1.AtPath:在哪个路径下创建文件夹
//2.withIntermediateDirectories:是否创建中间级文件夹
//3.attributes:文件夹属性
//4.error:若创建失败,返回错误原因
NSError *error = nil;
BOOL isSuccess = [fileManager createDirectoryAtPath:directoryPath withIntermediateDirectories:YES attributes:nil error:&error];
//判断文件夹是否创建成功
if (isSuccess == NO)
{
NSLog(@"创建失败,原因:%@",error);
}
}
}
#pragma mark - **************** 拷贝
- (IBAction)copyClick:(UIButton *)sender
{
NSFileManager *fileManager = [NSFileManager defaultManager];
//1.源路径
NSString *filePath = [self getFilePath:@"a.plist"];
//2.目标路径
NSString *tmpPath = NSTemporaryDirectory();
NSString *filePath2 = [tmpPath stringByAppendingPathComponent:@"b.plist"];
//3.拷贝
NSError *error = nil;
[fileManager copyItemAtPath:filePath toPath:filePath2 error:&error];
}
#pragma mark - **************** 移动
- (IBAction)moveClick:(UIButton *)sender
{
NSFileManager *manager = [NSFileManager defaultManager];
//1.源路径
NSString *path1 = [self getFilePath:@"class"];
//2.目标路径
NSString *path2 = [NSTemporaryDirectory() stringByAppendingPathComponent:@"class2"];
//3.移动
NSError *error = nil;
[manager moveItemAtPath:path1 toPath:path2 error:&error];
}
#pragma mark - **************** 删除
- (IBAction)deleteClick:(UIButton *)sender
{
NSFileManager *manager = [NSFileManager defaultManager];
//1.路径
NSString *path = [NSTemporaryDirectory() stringByAppendingPathComponent:@"class2/student"];
//2.删除
NSError *error = nil;
[manager removeItemAtPath:path error:&error];
}
#pragma mark - **************** 获取文件属性
- (IBAction)attributeClick:(UIButton *)sender
{
NSFileManager *manager = [NSFileManager defaultManager];
//1.路径
NSString *path = [self getFilePath:@"a.plist"];
NSError *error = nil;
NSDictionary *dic = [manager attributesOfItemAtPath:path error:&error];
NSDate *date = [dic fileCreationDate];
NSLog(@"date = %@",date);
}
@end
二、多行选择
项目:SelectMutableLine0412
程序再次运行时读取数据:
1.创建基本表
2.处理单元格的 选中/取消选中
2.1 判断点击的Cell索引是否在_selectedRowArr中:
①在,取消选中
换图片 取消选中
移除 索引
②不在,选中
换图片 选中
添加 索引
3.数据存储(通知)
程序将要终止运行时,发出通知,存储数据
①获取filePath②writeToFile。
4.数据读取
程序再次运行时,从沙盒中取出数据
①获取fileManager②获取filePath③读取
源码:
static NSString *cellId = @"cell";
@implementation ViewController
/**
1.创建基本表
2.处理单元格的选中
3.处理取消单元格选中
4.数据存储(通知)
5.数据读取
*/
- (void)viewDidLoad
{
[super viewDidLoad];
//当程序退出时,系统会发出通知
NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
[center addObserver:self selector:@selector(saveData) name:UIApplicationWillTerminateNotification object:nil];
//1.数据源
_movieArr = [[NSMutableArray alloc]initWithObjects:@"火锅英雄",@"奇幻森林",@"X特遣队",@"寻龙诀",@"疯狂动物城",@"伦敦陷落",@"蜘蛛侠",@"1",@"落",@"侠", nil];
//每次启动程序,先从沙盒中读取数据_selectedRowArr
//判断沙盒某路径下是否存在数据文件
NSFileManager *fileManager = [NSFileManager defaultManager];
NSString *filePath = [self getFilePath:@"movie.plist"];
BOOL isExists = [fileManager fileExistsAtPath:filePath];
if (isExists)
{
//文件存在,读取
_selectedRowArr = [[NSMutableArray alloc]initWithContentsOfFile:filePath];
}
else
{
//文件不存在,初始化
_selectedRowArr = [[NSMutableArray alloc]init];
}
//2.创建表
UITableView *tableView = [[UITableView alloc]initWithFrame:self.view.frame style:UITableViewStylePlain];
tableView.delegate = self;
tableView.dataSource = self;
tableView.rowHeight = 80;
[self.view addSubview:tableView];
[tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:cellId];
[tableView release];
}
#pragma mark - **************** 获取路径
- (NSString *)getFilePath:(NSString *)name
{
NSString *doc = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0];
NSLog(@"%@",doc);
return [doc stringByAppendingString:name];
}
#pragma mark - **************** 收到通知,保存数据
- (void)saveData
{
NSString *filePath = [self getFilePath:@"movie.plist"];
[_selectedRowArr writeToFile:filePath atomically:YES];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellId forIndexPath:indexPath];
cell.imageView.image = [UIImage imageNamed:@"star_half"];
for (NSNumber *number in _selectedRowArr)
{
if (indexPath.row == [number integerValue])
{
cell.imageView.image = [UIImage imageNamed:@"star_full"];
}
}
cell.textLabel.text = [_movieArr objectAtIndex:indexPath.row];
return cell;
}
#pragma mark - **************** 点击单元格
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
//4.判断当前点击的Cell索引是否在_selectedRowArr中
//两种情况:
//1.在
//2.不在
BOOL isSelect = NO;
for (NSNumber *number in _selectedRowArr)
{
NSInteger selectedRow = [number integerValue];
if (selectedRow == indexPath.row)
{
//已经被选中
isSelect = YES;
}
}
//1.找到当前点击的单元格
UITableViewCell *selectedCell = [tableView cellForRowAtIndexPath:indexPath];
NSNumber *number = [NSNumber numberWithInteger:indexPath.row];
//被选中,取消选中
if (isSelect)
{
//2.改变单元格上的图片
selectedCell.imageView.image = [UIImage imageNamed:@"star_half"];
//3.索引从数组中移除
[_selectedRowArr removeObject:number];
}
//未被选中
else
{
//2.改变单元格上的图片
selectedCell.imageView.image = [UIImage imageNamed:@"star_full"];
//3.将选中的单元格索引存进数组中
[_selectedRowArr addObject:number];
}
}
@end
三、对象序列化
项目:ObjectSerialization0412
NSUserDefaults/writeToFile不能直接存储自定义类
结论:
数组/字典/字符串/NSData可以直接使用NSUserDefaults/writeToFile的方式将数据写入沙盒,因为这些类都实现了NSCoding协议
将自定义类对象写入沙盒的条件:
1.实现NSCoding协议
2.对象序列化
(一)序列化 方法1
序列化:
NSKeyedArchiver:编码器
作用:将一个实现NSCoding协议的对象转换为二进制数据(NSData)
1.编码
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:people];
2.写入沙盒
[data writeToFile:[self getFilePath] atomically:YES];
反序列化:
NSKeyedUnarchiver:解码器
1.读取数据
NSData *data = [NSData dataWithContentsOfFile:[self getFilePath]];
2.解码
People *people = [NSKeyedUnarchiver unarchiveObjectWithData:data];
(二)方法2
序列化:
1.创建容器NSMutableData,保存要编码的对象
NSMutableData *mData = [[NSMutableData alloc]init];
2.创建序列化器,指定要编码的对象容器
NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc]initForWritingWithMutableData:mData];
3.编码
[archiver encodeObject:people forKey:@"p"];
4.结束编码
[archiver finishEncoding];
5.写入文件
[mData writeToFile:[self getFilePath] atomically:YES];
反序列化:
1.读取数据
NSMutableData *mData = [[NSMutableData alloc]initWithContentsOfFile:[self getFilePath]];
2.创建编码器
NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc]initForReadingWithData:mData];
3.解码
People *people = [unarchiver decodeObjectForKey:@"p"];
4.结束解码
[unarchiver finishDecoding];
源码:
@implementation People
#pragma mark - **************** 编码(对People类对象内的每一个属性进行编码)
- (void)encodeWithCoder:(NSCoder *)aCoder
{
[aCoder encodeObject:_name forKey:@"name"];
[aCoder encodeInteger:_age forKey:@"age"];
}
#pragma mark - **************** 解码
- (id)initWithCoder:(NSCoder *)aDecoder
{
self = [super init];
if (self)
{
self.name = [aDecoder decodeObjectForKey:@"name"];
self.age = [aDecoder decodeIntegerForKey:@"age"];
}
return self;
}
#pragma mark - **************** 重写description方法,用于自定义对象的输入内容(NSLog输出的内容)
- (NSString *)description
{
return [NSString stringWithFormat:@"%@--%d",self.name,self.age];
}
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
NSLog(@"%@",NSHomeDirectory());
People *people = [People new];
people.name = @"张三";
people.age = 30;
NSArray *array = @[people];
//不能直接存储自定义类
//1.NSUserDefaults不行
// NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
//①
// [defaults setObject:people forKey:@"p"];
//②
// [defaults setObject:array forKey:@"p"];
//2.writeToFile也不可以
// NSString *path = [NSHomeDirectory() stringByAppendingPathComponent:@"Documents/array.plist"];
// [array writeToFile:path atomically:YES];
//结论:
//数组/字典/字符串/NSData可以直接使用NSUserDefaults/writeToFile的方式将数据写入沙盒,因为这些类都实现了NSCoding协议
//将自定义类对象写入沙盒的条件:
//1.实现NSCoding协议
//2.对象序列化:
}
//对象序列化
- (IBAction)archiverClick:(UIButton *)sender
{
People *people = [People new];
people.name = @"张三";
people.age = 30;
//对象序列化:
//NSKeyedArchiver:编码器
//作用:将一个实现NSCoding协议的对象转换为二进制数据(NSData)
//1.编码
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:people];
//2.写入沙盒
[data writeToFile:[self getFilePath] atomically:YES];
}
//对象反序列化
- (IBAction)unarchiverClick:(UIButton *)sender
{
//反序列化
//NSKeyedUnarchiver
//1.读取
NSData *data = [NSData dataWithContentsOfFile:[self getFilePath]];
//2.对数据进行解码
People *people = [NSKeyedUnarchiver unarchiveObjectWithData:data];
NSLog(@"%@",people);
}
@end
项目:ObjectSerialization_Tow0412
#pragma mark - **************** 序列化
- (IBAction)archiverClick:(UIButton *)sender
{
People *people = [People new];
people.name = @"李四";
people.phoneNum = @"1234325423";
//1.创建一个NSMutableData,作为一个容器,保存要编码的对象
NSMutableData *mData = [[NSMutableData alloc]init];
//2.创建序列化器,并且指定要编码的对象保存的位置
NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc]initForWritingWithMutableData:mData];
//3.编码
[archiver encodeObject:people forKey:@"p"];
//4.结束编码
[archiver finishEncoding];
//5.写入文件
BOOL is = [mData writeToFile:[self getFilePath] atomically:YES];
if (is)
{
NSLog(@"成功");
}
}
#pragma mark - **************** 反编码
- (IBAction)unarchiverClick:(UIButton *)sender
{
//1.从沙盒中读取数据
NSMutableData *mData = [[NSMutableData alloc]initWithContentsOfFile:[self getFilePath]];
//2.创建编码器
NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc]initForReadingWithData:mData];
//3.解码
People *people = [unarchiver decodeObjectForKey:@"p"];
//4.结束解码
[unarchiver finishDecoding];
NSLog(@"%@",people);
}
四、对容器类的拷贝
项目:FullyCopy0412
完全拷贝
方法1:
initWithArray:copyItems:对数组中的每一个元素调用 copy方法
条件:
1.元素实现 NSCoping 协议
2.元素是可变对象
方法2:序列化
条件:数组/元素 必须实现 NSCoding 协议
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:array];
反序列化
NSArray *array4 = [NSKeyedUnarchiver unarchiveObjectWithData:data];
源码:
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
//可变
NSString *text = @"12345";
// //不可变
// NSMutableString *text = [NSMutableString stringWithFormat:@"12345"];
NSArray *array = @[text];
// NSArray *array = @[mText];
NSArray *array1 = [array copy];//浅拷贝,拷贝指针
NSArray *array2 = [array mutableCopy];//深拷贝,拷贝对象
//完全拷贝:
//方法1:
//initWithArray: copyItems:对数组中的每一个元素调用 copy方法
//条件:
//1.元素实现 NSCoping 协议
//2.元素是可变对象
NSArray *array3 = [[NSArray alloc]initWithArray:array copyItems:YES];
//方法2:序列化
//条件:数组/元素 必须实现 NSCoding 协议
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:array];
//反序列化
NSArray *array4 = [NSKeyedUnarchiver unarchiveObjectWithData:data];
//输出
NSLog(@"---%p---%p---%p---%p---%p",array,array1,array2,array3,array4);
//对于系统容器类来说,copy/mutableCopy,容器内部的元素都是浅拷贝,
NSLog(@"===%p===%p===%p===%p===%p",array[0],array1[0],array2[0],array3[0],array4[0]);
}
@end