iOS之文件管理(五)—NSKeyedArchive 文件归档
一,前言
使用情景:
在我们的实际开发过程中,为了更好的用户体验,可能需要在APP上存储用户的某些信息,比如淘宝APP会记录用户曾经填写过的收货地址。这种数据不方便用前面提到的NSUserDefaults来存储:
一是,因为地址数据是一个模型,NSUserDefaults只能用于NSString、NSArray、NSDictionary等常用的数据类型;
二是,用户还会经常对它进行增删改等操作,NSUserDefaults无法满足。此时,用NSKeyedArchive归档的形式来存储地址模型数据最符合要求。
二,使用方法
(1)创建地址模型CLVoiceApplyAddressModel
CLVoiceApplyAddressModel.h文件
#import <Foundation/Foundation.h> @interface CLVoiceApplyAddressModel : NSObject<NSCoding> //用于存储多个地址时,标记用户选中的状态 @property (nonatomic, copy) NSString *state; @property (nonatomic, copy) NSString *name; @property (nonatomic, copy) NSString *phoneNum; @property (nonatomic ,copy) NSString *mainAddress; @property (nonatomic ,copy) NSString *detailAddress; +(instancetype)AddressModelWithDict:(NSDictionary *)dict; -(instancetype)initAddressModelWithDict:(NSDictionary *)dict; @end
CLVoiceApplyAddressModel.m文件
#import "CLVoiceApplyAddressModel.h" @implementation CLVoiceApplyAddressModel -(void)encodeWithCoder:(NSCoder *)aCoder{ [aCoder encodeObject:_state forKey:@"state"]; [aCoder encodeObject:_name forKey:@"name"]; [aCoder encodeObject:_phoneNum forKey:@"phoneNum"]; [aCoder encodeObject:_mainAddress forKey:@"mainAddress"]; [aCoder encodeObject:_detailAddress forKey:@"detailAddress"]; } -(instancetype)initWithCoder:(NSCoder *)aDecoder{ self = [super init]; if (self) { self.state= [aDecoder decodeObjectForKey:@"state"]; self.name = [aDecoder decodeObjectForKey:@"name"]; self.phoneNum = [aDecoder decodeObjectForKey:@"phoneNum"]; self.mainAddress = [aDecoder decodeObjectForKey:@"mainAddress"]; self.detailAddress = [aDecoder decodeObjectForKey:@"detailAddress"]; }else{ return nil; } return self; } +(instancetype)AddressModelWithDict:(NSDictionary *)dict{ return [[self alloc] initAddressModelWithDict:dict]; } -(instancetype)initAddressModelWithDict:(NSDictionary *)dict{ if (self = [super init]) { self.state =[dict objectForKey:@"state"]; self.name =[dict objectForKey:@"name"]; self.phoneNum =[dict objectForKey:@"phoneNum"]; self.mainAddress =[dict objectForKey:@"mainAddress"]; self.detailAddress =[dict objectForKey:@"detailAddress"]; } return self; } @end
为了实现对归档地址的操作,我们专门创建了一个工具类:CLInvoiceApplyAddressModelTool。
#import <Foundation/Foundation.h> @class CLVoiceApplyAddressModel; @interface CLInvoiceApplyAddressModelTool : NSObject +(NSArray *)allAddressInfo; +(CLVoiceApplyAddressModel *)currentSelectedAddress; +(void)update; +(void)updateAddressInfoAfterDeleted; +(void)setSelectedAddressByNewInfoArray:(NSArray *)infoArray; +(void)addInfo:(CLVoiceApplyAddressModel *)info; +(void)removeInfoAtIndex:(NSUInteger)index; +(void)updateInfoAtIndex:(NSUInteger)index withInfo:(CLVoiceApplyAddressModel *)info; +(void)removeAllInfo; @end
#import "CLInvoiceApplyAddressModelTool.h" #import "CLVoiceApplyAddressModel.h" #define AddressInfosPath [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:@"addressInfo1.data"] @implementation CLInvoiceApplyAddressModelTool static NSMutableArray *_addressInfos; +(NSArray *)allAddressInfo{ _addressInfos = [NSKeyedUnarchiver unarchiveObjectWithFile:AddressInfosPath]; if (!_addressInfos) _addressInfos = [NSMutableArray array]; return _addressInfos; } +(CLVoiceApplyAddressModel *)currentSelectedAddress{ CLVoiceApplyAddressModel *currentAddress; BOOL hasSelectedAddress = NO; if ([self allAddressInfo].count) { for (CLVoiceApplyAddressModel *info in _addressInfos) { if ([info.state isEqualToString:@"1"]) { currentAddress = info; hasSelectedAddress = YES; break; }; } }else if([self allAddressInfo].count == 0 || hasSelectedAddress){ currentAddress = nil; } return currentAddress; } +(void)update{ [NSKeyedArchiver archiveRootObject:_addressInfos toFile:AddressInfosPath]; } +(void)updateAddressInfoAfterDeleted{ if (_addressInfos.count) { if (![self currentSelectedAddress]) { CLVoiceApplyAddressModel *info = [CLInvoiceApplyAddressModelTool allAddressInfo][0]; info.state = @"1"; [CLInvoiceApplyAddressModelTool updateInfoAtIndex:0 withInfo:info]; } } } +(void)setSelectedAddressByNewInfoArray:(NSArray *)infoArray{ [NSKeyedArchiver archiveRootObject:infoArray toFile:AddressInfosPath]; } +(void)addInfo:(CLVoiceApplyAddressModel *)info{ if (!_addressInfos.count) { _addressInfos = [NSMutableArray array]; } for (CLVoiceApplyAddressModel *oldInfo in _addressInfos ) { oldInfo.state = @"0"; } [_addressInfos insertObject:info atIndex:0]; [self update]; } + (void)removeInfoAtIndex:(NSUInteger)index { [_addressInfos removeObjectAtIndex:index]; [self update]; } + (void)removeAllInfo{ [_addressInfos removeAllObjects]; [self update]; } + (void)updateInfoAtIndex:(NSUInteger)index withInfo:(CLVoiceApplyAddressModel *)info { [_addressInfos replaceObjectAtIndex:index withObject:info]; [self update]; } @end