IOS文件管理系统:沙盒、NSFileManager、NSFileHandle、NSCoding、NSKeyedArchiver解析

什么是沙盒?

苹果为我们每个app都分配了一个固定的文件夹,我们在开发过程中可以向文件夹存入我们想要存储的数据,同时也能从这些文件夹取这些数据,但是我们不能取到其他app所存储的数据。简单说,沙盒就是这个文件夹。
沙盒是苹果的一种安全机制的设计,就是一个app只能访问该app对应的文件夹,以及一些相关的资源,两个app之间是不能共享文件的。每个app只能访问自己沙盒中的文件的。而沙盒就是一个存储app资源的地方。它主要包括bundles文件和Datas文件。而bundles文件主要是系统来管理的,我们开发app的时候主要访问Datas文件。
在这里插入图片描述
沙盒文件结构
在这里插入图片描述
documents主要存储用户产生的数据,它支持用户共享。
library主要我们在开发app的时候使用,我们可以在这里创建自己的文件夹。
在这里插入图片描述

获取沙盒地址

使用函数NSSearchPathForDirectoriesInDomains我们可以获取IOS的某个app的沙盒地址,它有三个参数,第一个参数是枚举参数,它可以设定获取某个具体文件夹的地址,比如document,library,或者library下的cache文件夹地址。第二个参数是设定是取用户文件夹还是系统文件夹

//得到该应用程序的沙盒地址,cache文件夹地址,用户路径下
   NSArray *pathArray = NSSearchPathForDirectoriesInDomains(NSCachesDirectory,NSUserDomainMask,YES);
   NSString *cachePath = [pathArray firstObject]; //cache的地址就是第一位

在这里插入图片描述

IOS文件管理

在IOS文件管理中,我们最主要使用的两个类,一个是NSFileManager,一个是NSFileHandle。从这两个类的命名我们就可以猜到,NSFileManager主要功能就是文件管理,比如文件的创建,删除,移动和复制等。它不是针对文件的内容的,而是针对文件和文件夹的操作。NSFileHandle就是对NSFileManager的一个补充,可以对文件中存储的数据做截断或者追加。
在这里插入图片描述
在这里插入图片描述
这里我展示了使用NSFileManager创建GTData文件夹和list文件的操作

    //创建一个NSFileManager,用于文件的创建
    NSFileManager *fileManager = [NSFileManager defaultManager];
    
    //实现在cache文件夹下创建GTData 文件夹
    //创建文件夹路径
    NSString *dataPath = [cachePath stringByAppendingPathComponent:@"GTPath"];
    NSError *createError;
    //这一步才是创建操作
    [fileManager createDirectoryAtPath:dataPath withIntermediateDirectories:YES attributes:nil error:&createError];
    
    //在GTPath文件夹下创建list 文件
    //创建文件路径
    NSString *listDataPath = [dataPath stringByAppendingPathComponent:@"list"];
    //在List文件中保存abc字符串
    NSData *listData = [@"abc" dataUsingEncoding:NSUTF8StringEncoding];
    [fileManager createFileAtPath: listDataPath contents:listData attributes:nil];

	//查询文件
    __unused BOOL fileExist = [fileManager fileExistsAtPath:listDataPath];
    
    //删除指定路径下的文件
    if(fileExist){
        [fileManager removeItemAtPath:listDataPath error:nil];
    }

使用NSFileHandle在list文件末尾追加数据的操作

    创建fileHandler,用于文件处理,增删查改
    NSFileHandle *fileHandler = [NSFileHandle fileHandleForUpdatingAtPath:listDataPath];
    [fileHandler seekToEndOfFile]; //移动到文件末尾
    [fileHandler writeData:[@"def" dataUsingEncoding:NSUTF8StringEncoding]]; //添加数据
    [fileHandler synchronizeFile];  //立即写入磁盘
    [fileHandler closeFile];  //关闭文件

文件存储-序列化和反序列化

当我们从网络上请求了数据之后,我们需要把这些数据进行保存,我们可以采用苹果系统为我们提供的NSCoding协议来实现。
如果我们某个对象使用了NSCoding,需要实现其中的两个方法:

- (void)encodeWithCoder:(NSCoder *)coder;
- (nullable instancetype)initWithCoder:(NSCoder *)coder; // NS_DESIGNATED_INITIALIZER

在这里插入图片描述

比如,我们使用GTListItem对象数据来保存请求到的数据,我们可以使用NSCoding的子类NSKeyedArchiver来把这些数据保存起来,也可以取出。
在这里插入图片描述
但是,我们在使用NSKeyedArchiver对GTListItem序列化和反序列化的之前,我们需要GTListItem先支持NSSecureCoding协议,并且实现该协议指定的函数。
使用NSSecureCoding协议,我们还需要实现一个函数:

@protocol NSSecureCoding <NSCoding>
@required
// This property must return YES on all classes that allow secure coding. Subclasses of classes that adopt NSSecureCoding and override initWithCoder: must also override this method and return YES.
// The Secure Coding Guide should be consulted when writing methods that decode data.
@property (class, readonly) BOOL supportsSecureCoding;
@end

从代码中我们可以看到,NSSecureCoding协议是NSCoding子协议,是安全版本的NSCoding协议。
在这里插入图片描述
接下来,我就展示一下我把自定义的GTListItem对象实现序列化和反序列化的操作。首先,需要增加NSSecureCoding协议。

/// 列表结构化数据 ,支持NSSecureCoding协议,可以保存GTListItem的数据
@interface GTListItem : NSObject <NSSecureCoding>

@property(nonatomic,copy, readwrite) NSString *category ;
@property(nonatomic,copy, readwrite) NSString * picUrl;
@property(nonatomic,copy, readwrite) NSString * uniqueKey;
@property(nonatomic,copy, readwrite) NSString * title;
@property(nonatomic,copy, readwrite) NSString * date;
@property(nonatomic,copy, readwrite) NSString * authorName;
@property(nonatomic,copy, readwrite) NSString * articleUrl;

-(void) configWithDictionary :(NSDictionary *) dictionary;

@end

实现NSSecureCoding指定的协议函数

#pragma mark -NSSecureCoding

-(nullable instancetype) initWithCoder:(NSCoder *)coder{
    if(self = [super init ]){
        self.category = [coder decodeObjectForKey:@"category"];
        self.picUrl = [coder decodeObjectForKey:@"picUrl"];
        self.uniqueKey = [coder decodeObjectForKey:@"uniqueKey"];
        self.title = [coder decodeObjectForKey:@"title"];
        self.date = [coder decodeObjectForKey:@"date"];
        self.authorName = [coder decodeObjectForKey:@"authorName"];
        self.articleUrl = [coder decodeObjectForKey:@"articleUrl"];
    }
    return self;
}

-(void) encodeWithCoder:(NSCoder *)coder{
    [coder encodeObject:self.category forKey:@"category"];
    [coder encodeObject:self.picUrl forKey:@"picUrl"];
    [coder encodeObject:self.uniqueKey forKey:@"uniqueKey"];
    [coder encodeObject:self.title forKey:@"title"];
    [coder encodeObject:self.date forKey:@"date"];
    [coder encodeObject:self.authorName forKey:@"authorName"];
    [coder encodeObject:self.articleUrl forKey:@"articleUrl"];
}

+(BOOL) supportsSecureCoding{
    return YES;
}

实现NSSecureCoding之后,就可以对GTListItem对象执行序列化和反序列化了

//获取沙盒地址,存储数据,参数传入元素为GTListItem对象的数组
-(void) archiveListDataWithArray:(NSArray<GTListItem*> *)array{
    //得到该应用程序的沙盒地址
   NSArray *pathArray = NSSearchPathForDirectoriesInDomains(NSCachesDirectory,NSUserDomainMask,YES);
    NSString *cachePath = [pathArray firstObject]; //cache的地址就是第一位
    
    //创建一个NSFileManager,用于文件的创建
    NSFileManager *fileManager = [NSFileManager defaultManager];
    
    //实现在cache文件夹下创建GTData 文件夹
    //创建文件夹路径
    NSString *dataPath = [cachePath stringByAppendingPathComponent:@"GTPath"];
    NSError *createError;
    //这一步才是创建操作
    [fileManager createDirectoryAtPath:dataPath withIntermediateDirectories:YES attributes:nil error:&createError];
    
    //在GTPath文件夹下创建list 文件
    //创建文件路径
    NSString *listDataPath = [dataPath stringByAppendingPathComponent:@"list"];
    //将请求回来的数据序列化为二进制文件
    NSData *listData = [NSKeyedArchiver archivedDataWithRootObject:array requiringSecureCoding:YES error:nil];
    //将该二进制文件存储在list文件里
    [fileManager createFileAtPath: listDataPath contents:listData attributes:nil];
    
    //把存储在list文件中的二进制数据读取出来
    NSData *readListData = [fileManager contentsAtPath:listDataPath];
    //执行反序列化
    id unarchiveObj = [NSKeyedUnarchiver unarchivedObjectOfClasses:[NSSet setWithObjects:[NSArray class],[GTListItem class], nil] fromData:readListData error:nil];
    
}

以上我们就展示了把app从网络请求回来的数据以GTListItem对象的形式保存,并将该数据以二进制形式序列化保存在app的指定文件夹下,并且从指定文件夹下反序列化(取出数据)的操作。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值