10FileManager_SelectMutableLine_ObjectSerialization_FullyCopy

大纲

一、文件管理器
项目: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

你可能感兴趣的:(10FileManager_SelectMutableLine_ObjectSerialization_FullyCopy)