IOS开发学习日记(九)

目录

IOS沙盒机制和文件结构

IOS文件管理

NSFileManager

NSFileHandle

简单实现创建、查询、删除文件及追加内容

IOS中的序列化

NSCoder

NSKeyedArchiver

NSCoding

 简单实现数据的序列化与反序列化

开源存储方案对比分析

NSUserDefault

开源框架


IOS沙盒机制和文件结构

 沙盒机制:App只能访问对应的文件夹及相关资源,App之间无法共享文件等资源

Document:可以进行备份和恢复,体积较大,一般存档用户数据

Library:开发者最常使用的文件夹,可以自定义子文件夹

        Preference:用户偏好设置,NSUserDefault,支持备份

        Cache:不需要缓存的,体积较大,一般的删除缓存操作

        ......

SystemData:系统文件

tmp:临时文件不会备份,启动时可能会被删除

IOS获取沙盒地址:NSPathUtilities

-(void) _getSandBoxPath{
    NSArray *pathArray = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSLog(@"");
}

IOS文件管理

NSFileManager

        1.单例,提供App内文件&文件夹管理功能

        2.创建、删除、查询、移动、复制文件

        3.读取文件内容&属性

        4.通过NSURL或者NSString作为Path

        NSFileManagerDelegate:提供移动、复制、删除等操作的具体自定义实现

NSFileHandle

        1.读取文件&写文件

        2.读取指定长度&在指定位置追加/截断

        3.截断&立即刷新

        4.常用语追加数据

// 创建
+ (nullable instancetype)fileHandleForReadingAtPath:(NSString *)path;
+ (nullable instancetype)fileHandleForWritingAtPath:(NSString *)path;
+ (nullable instancetype)fileHandleForUpdatingAtPath:(NSString *)path;

// 读&写
- (NSData *)readDataOfLength:(NSInteger)length;
- (void)seekToFileOffset:(unsigned long long)offset;
- (void)writeData:(NSData *)data;

简单实现创建、查询、删除文件及追加内容

-(void) _getSandBoxPath{
    
    NSArray *pathArray = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
    NSString *cachePath = [pathArray firstObject];
    
    NSFileManager *fileManager = [NSFileManager defaultManager];
    NSString *dataPath = [cachePath stringByAppendingPathComponent:@"GSCData"];    // cache文件夹下创建GSCData子文件夹
    
    NSError *createError;
    [fileManager createDirectoryAtPath:dataPath withIntermediateDirectories:YES attributes:nil error:&createError];
    
    NSString *listDataPath = [dataPath stringByAppendingPathComponent:@"list"]; // 创建文件
    NSData *listData = [@"abc" dataUsingEncoding:NSUTF8StringEncoding];
    
    [fileManager createFileAtPath:listDataPath contents:listData attributes:nil];
    
    //查询文件
    BOOL fileExist = [fileManager fileExistsAtPath:listDataPath];
    
//    //删除文件
//    if(fileExist){
//        [fileManager removeItemAtPath:listDataPath error:nil];
//    }
//    
    // 追加文件内容
    NSFileHandle *fileHandle = [NSFileHandle fileHandleForUpdatingAtPath:listDataPath];
    [fileHandle seekToEndOfFile];
    [fileHandle writeData:[@"def" dataUsingEncoding:NSUTF8StringEncoding]];
    [fileHandle synchronizeFile];
    [fileHandle closeFile];

}

IOS中的序列化

NSCoder

        1.归档(序列化)&解归档(反序列化)

        2.提供简单的函数,在Object和二进制数据见进行转换

        3.抽象类 具体功能需要子类实现

// encode
- (void)encodeObject:(nullable id)object forKey:(NSString *)key;
- (void)encodeBool:(BOOL)value forKey:(NSString *)key;
- (void)encodeInt:(int)value forKey:(NSString *)key;
- (void)encodeInt32:(int32_t)value forKey:(NSString *)key;
- (void)encodeInt64:(int64_t)value forKey:(NSString *)key;
- (void)encodeFloat:(float)value forKey(NSString *)key;
- (void)encodeDouble:(double)value forKey(NSString *)key;

//decode 
- (nullable id)decodeObjectForKey:(NSString*)key;
- (BOOL)decodeBoolForKey:(NSString *)key;
- (int)decodeIntForKey:(NSString *)key;
- (int32_t)decodeInt32ForKey:(NSString *)key;
- (int64_t)decodeInt64ForKey:(NSString *)key;
- (float)decodeFloatForKey:(NSString *)key;
- (double)decodeDoubleForKey:(NSString *)key;

为了向前向后兼容,不依赖顺心,所以需要将非基本数据对应到key存储

NSKeyedArchiver

        1.NScoder的子类

        2.提供简单的函数,在Object和二进制数据之间进行转换

        3.提供基本的delegate

        4.需要Object自己处理Key-Value的对应关系

NSCoding

对于Objecy等序列化&反序列化协议

·NSArray&NSDictionary等类型系统已经实现协议

·NSSecureCoding

        1.解决文件替换攻击

        2.序列化时规定Class

 简单实现数据的序列化与反序列化

//实现NSSecureCoding

//
//  GSCListItem.h
//  GSCApp1
//
//  Created by gsc on 2024/5/23.
//

#import <Foundation/Foundation.h>

NS_ASSUME_NONNULL_BEGIN


/*
 列表结构化属性
 */

@interface GSCListItem : NSObject <NSSecureCoding>

@property (nonatomic, copy, readwrite)  NSString * category;
//@property (nonatomic, copy, readwrite)  NSString * isContent;
@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

NS_ASSUME_NONNULL_END


//
//  GSCListItem.m
//  GSCApp1
//
//  Created by gsc on 2024/5/23.
//

#import "GSCListItem.h"

@implementation GSCListItem

#pragma mark - NSSecureCoding

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

-(void)encodeWithCoder:(NSCoder *)aCoder{
    [aCoder encodeObject:self.category forKey:@"category"];
    [aCoder encodeObject:self.picUrl forKey:@"thumbnail_pic_s"];
    [aCoder encodeObject:self.uniquekey forKey:@"uniquekey"];
    [aCoder encodeObject:self.title forKey:@"title"];
    [aCoder encodeObject:self.date forKey:@"date"];
    [aCoder encodeObject:self.authorName forKey:@"author_name"];
    [aCoder encodeObject:self.articleUrl forKey:@"url"];

}

#pragma mark - NSSecureCoding
+(BOOL)supportsSecureCoding{
    return YES;
}

#pragma mark - public method#pragma mark - NSSecureCoding

- (void)configWithDictionary:(NSDictionary *)dictionary {
    self.category = [dictionary objectForKey:@"category"];
    self.picUrl = [dictionary objectForKey:@"thumbnail_pic_s"];
    self.uniquekey = [dictionary objectForKey:@"uniquekey"];
    self.title = [dictionary objectForKey:@"title"];
    self.date = [dictionary objectForKey:@"date"];
    self.authorName = [dictionary objectForKey:@"author_name"];
    self.articleUrl = [dictionary objectForKey:@"url"];
}


@end

//
//  GSCListLoader.m
//  GSCApp1
//
//  Created by gsc on 2024/5/20.
//

#import "AFNetworking/AFNetworking.h"
#import "GSCListItem.h"
#import "GSCListLoader.h"

@implementation GSCListLoader

- (void)loadListDataWithFinishBlock:(GSCListLoaderFinishBlock)finishBlock {
    NSString *urlString = @"http://v.juhe.cn/toutiao/index?type=top&key=97ad001bfcc2082e2eeaf798bad3d54e";
    NSURL *listURL = [NSURL URLWithString:urlString];
    NSURLSession *session = [NSURLSession sharedSession];
    
    __weak typeof(self) weakself = self;
    NSURLSessionTask *dataTask = [session dataTaskWithURL:listURL
                                        completionHandler:^(NSData *_Nullable data, NSURLResponse *_Nullable response, NSError *_Nullable error) {
        __strong typeof(weakself) strongSelf = weakself;
        NSError *jsonError;
        id jsonObj = [NSJSONSerialization JSONObjectWithData:data
                                                     options:0
                                                       error:&jsonError];

        NSArray *dataArray = [((NSDictionary *)[((NSDictionary *)jsonObj) objectForKey:@"result"]) objectForKey:@"data"];
        NSMutableArray *listItemArray = @[].mutableCopy;

        for (NSDictionary *info in dataArray) {
            GSCListItem *listItem = [[GSCListItem alloc] init];
            [listItem configWithDictionary:info];
            [listItemArray addObject:listItem];
        }
        [strongSelf _archiveListDataWithArray:listItemArray.copy];
        dispatch_async(dispatch_get_main_queue(), ^{
                           if (finishBlock) {
                               finishBlock(error == nil, listItemArray);
                           }
                       });
    }];

    [dataTask resume];
}

-(void) _archiveListDataWithArray:(NSArray<GSCListItem *> *)array{
    
    NSArray *pathArray = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
    NSString *cachePath = [pathArray firstObject];
    
    NSFileManager *fileManager = [NSFileManager defaultManager];
    NSString *dataPath = [cachePath stringByAppendingPathComponent:@"GSCData"];    // cache文件夹下创建GSCData子文件夹
    
    NSError *createError;
    [fileManager createDirectoryAtPath:dataPath withIntermediateDirectories:YES attributes:nil error:&createError];
    
    NSString *listDataPath = [dataPath stringByAppendingPathComponent:@"list"]; // 创建文件
//    NSData *listData = [@"abc" dataUsingEncoding:NSUTF8StringEncoding];
    
    // 数据序列化
    NSData *listData = [NSKeyedArchiver archivedDataWithRootObject:array requiringSecureCoding:YES error:nil];
    
    [fileManager createFileAtPath:listDataPath contents:listData attributes:nil];
    
    NSData *readListData = [fileManager contentsAtPath:listDataPath];
    
    // 数据反序列化
    id unarchiveObj = [NSKeyedUnarchiver unarchivedObjectOfClasses: [NSSet setWithObjects:[NSArray class], [GSCListItem class], nil]
    fromData: readListData error:nil]; 
    
}


@end

开源存储方案

NSUserDefault

提供简单的key-value存储

        1.单例,存取轻量级的数据                        2.支持基本的数据类型

        3.一般用于用户的偏好设置                        4.保存Integer Float Double Bool

        5.升级安装后还可以继续使用                    6.保存NSArray NSData NSString NSDictionary

        7.文件存储在/Library/Preference下           7.复杂Model需要转化成NSData

-(void) _archiveListDataWithArray:(NSArray<GSCListItem *> *)array{
    
    NSArray *pathArray = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
    NSString *cachePath = [pathArray firstObject];
    
    NSFileManager *fileManager = [NSFileManager defaultManager];
    NSString *dataPath = [cachePath stringByAppendingPathComponent:@"GSCData"];    // cache文件夹下创建GSCData子文件夹
    
    NSError *createError;
    [fileManager createDirectoryAtPath:dataPath withIntermediateDirectories:YES attributes:nil error:&createError];
    
    NSString *listDataPath = [dataPath stringByAppendingPathComponent:@"list"]; // 创建文件
//    NSData *listData = [@"abc" dataUsingEncoding:NSUTF8StringEncoding];
    
    // 数据序列化
    NSData *listData = [NSKeyedArchiver archivedDataWithRootObject:array requiringSecureCoding:YES error:nil];
    
    [fileManager createFileAtPath:listDataPath contents:listData attributes:nil];
    
    NSData *readListData = [fileManager contentsAtPath:listDataPath];
    
    // 数据反序列化
    id unarchiveObj = [NSKeyedUnarchiver unarchivedObjectOfClasses: [NSSet setWithObjects:[NSArray class], [GSCListItem class], nil]
    fromData: readListData error:nil];
    
    [[NSUserDefaults standardUserDefaults] setObject:listData forKey:@"listData"];
    NSData *testListData = [[NSUserDefaults standardUserDefaults] dataForKey:@"listData"];
    id unarchiveObjTest = [NSKeyedUnarchiver unarchivedObjectOfClasses: [NSSet setWithObjects:[NSArray class], [GSCListItem class], nil]
    fromData: testListData error:nil];
}

开源框架

        系统级存储:NSUserData、keychain、通过NSKeyedArchiver归档后存文件、数据库CoreData

        key-value类型:LevelDB/MMKV/Realm

        关系数据库类型:SQLite/FMDB/WCDB

 

  • 34
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

我真的学不会了

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值