省市区三级联动数据本地序列化和反序列化

简介: 省市区三级联动数据本地序列化和反序列化

由于现在经常出现撤县建市,裁撤乡村,大城市把撤县设区以及区划调整,所以需要更新省市区的数据。

解决办法是后台从民政部获取官方省市区数据,录入数据库。后台增加接口让前端调用,获取实时省市区实时数据。

由于省市区数据超过4000条记录,数据量极大,这种实时获取的方式十分费时间和流量。所以要做本地化处理。

把省市区版本号存入系统plist文件([[NSUserDefaults standardUserDefaults] objectForKey:key]),应用启动时,判断版本号是否一致,若不一致清除本地数据,若一致加载本地化数据放入内存,以便于有获取省市区。

在使用的页面判断内存中是否有省市区数据,若没有就调用省市区接口并本地化数据。

当然你若认为把省市区本地化数据加载如内存浪费内存,也使用时获取就可以。一般的手机内存都很大,也不在乎那几百k的内存。

BGChinaAddressEntity.h

#import <UIKit/UIKit.h>

@interface BGChinaAddressEntity : NSObject<NSCoding>

@property (nonatomic, strong) NSString *name;
@property (nonatomic, strong) NSString *code;
@property (nonatomic, strong) NSString *pcode;
@property (nonatomic, strong) NSString *subFilePath;
@property (nonatomic, strong) NSMutableArray *sub;

-(BGChinaAddressEntity *)updateWithName:(NSString *)name code:(NSString *)code pcode:(NSString *)pcode subFilePath:(NSString *)subFilePath;
@end

BGChinaAddressEntity.m

#import "BGChinaAddressEntity.h"

@implementation BGChinaAddressEntity

- (instancetype)init
{
    self = [super init];
    return self;
}


//将对象编码(即:序列化)
-(void) encodeWithCoder:(NSCoder *)aCoder
{
    [aCoder encodeObject:self.name forKey:@"name"];
    [aCoder encodeObject:(isCommonUnitEmptyString(self.pcode)?@"":self.pcode) forKey:@"pcode"];
    [aCoder encodeObject:self.code forKey:@"code"];
    [aCoder encodeObject:self.subFilePath forKey:@"subFilePath"];
}
//
//将对象解码(反序列化)
-(id) initWithCoder:(NSCoder *)aDecoder
{
    if (self=[super init])
    {
        self.name= [aDecoder decodeObjectForKey:@"name"];
        self.pcode= [aDecoder decodeObjectForKey:@"pcode"];
        self.code= [aDecoder decodeObjectForKey:@"code"];
        self.subFilePath= [aDecoder decodeObjectForKey:@"subFilePath"];
    }
    return (self);
    
}

-(BGChinaAddressEntity *)updateWithName:(NSString *)name code:(NSString *)code pcode:(NSString *)pcode subFilePath:(NSString *)subFilePath
{
    self.name = name;
    self.code = code;
    self.pcode = pcode;
    self.subFilePath = subFilePath;
    return self;
}

@property(nonatomic, assign) long long provinceCityDistrictVersion;
#ifndef LOCATION_DATA_DOCUMENT_DICRECTORY
//日志文档目录,若定义就把日志存在NSDocumentDirectory目录下,若不定义就存在NSCachesDirectory目录下
#define LOCATION_DATA_DOCUMENT_DICRECTORY
#endif
+(PPSingleObject *) sharedInstance
{
    static PPSingleObject *sharedInstace = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        sharedInstace = [[self alloc] init];
        sharedInstace.provinceCityDistrictVersion = [BITMobilePassword valueForKey:@"provinceCityDistrictVersion"]  == NULL ? 0 : [[BITMobilePassword valueForKey:@"provinceCityDistrictVersion"] longLongValue];
    });
    
    return sharedInstace;
}

序列化:

- (BOOL)isDirectory:(NSString *)filePath
{
    if(isEmptyString(filePath))
    {
        return NO;
    }
    NSNumber *isDirectory;
    NSURL *fileUrl = [NSURL fileURLWithPath:filePath];
    [fileUrl getResourceValue:&isDirectory forKey:NSURLIsDirectoryKey error:nil];
    return isDirectory.boolValue;
}

- (void)storageDataModelWithPath:(NSString *)path
                         dataArr:(NSMutableArray *)dataArr
                       directory:(NSString *)directory
{
    if(isCommonUnitEmptyString(path) || isCommonUnitEmptyString(directory))
    {
        return;
    }
    
    if (![self isDirectory:directory])
    {
        NSFileManager* fm = [NSFileManager defaultManager];
        [fm createDirectoryAtPath:directory  withIntermediateDirectories:YES attributes:nil error:nil];
    }
    
    if(![dataArr isKindOfClass:[NSArray class]] || (dataArr.count == 0))
    {
        //由于已经删除了地址的根目录,不需要重新删除文件或目录
        return;
    }
    NSMutableArray *arr = [NSMutableArray array];
    for(NSUInteger i = 0; i < dataArr.count; i++)
    {
        BGChinaAddressEntity *model = dataArr[i];
        if(![model isKindOfClass:[BGChinaAddressEntity class]])
        {
            return;
        }
        [arr addObject:model];
    }
    if(arr.count > 0)
    {
        NSData * tempArchive = [NSKeyedArchiver archivedDataWithRootObject:arr];
        BOOL result = [tempArchive writeToFile:path atomically:YES];
//        NSLog(@"result:%d", result);
        [BITMobilePassword setUserDefaultsValue:[NSString stringWithFormat:@"%lld", sProvinceCityDistrictVersion] key:@"provinceCityDistrictVersion"];
    }

}

- (void)deleteAddressAllFiles
{
#ifdef LOCATION_DATA_DOCUMENT_DICRECTORY
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
#else
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
#endif
    NSFileManager* fm = [NSFileManager defaultManager];
    NSString *path=[paths objectAtIndex:0];
    path = [path stringByAppendingPathComponent:sAddressData];
    if ([self isDirectory:path])
    {
        [fm removeItemAtPath:path error:nil];
    }
}

反序列化:

-(BOOL)judgeCanUseLoadLoctaionListData
{
    if(self.loadLoctaionListDataStaus == BGLoadLoctaionListDataStausProcessing)
    {
        if([[NSDate date] timeIntervalSince1970] - self.loadLoctaionListDataTime < LOAD_LOCATION_LIST_DATA_MAX_TIME)
        {
            return NO;
        }
        else
        {
            [self loadLoctaionData];
            return YES;
        }
    }
    else
    {
        return YES;
    }
    
}

#pragma mark - 加载本地数据
//加载我的订单和行程列表本地数据
-(void)loadLocationListDataBSD
{
    if((self.loadLoctaionListDataStaus == BGLoadLoctaionListDataStausProcessing) && ([[NSDate date] timeIntervalSince1970] - self.loadLoctaionListDataTime < LOAD_LOCATION_LIST_DATA_MAX_TIME))
    {
        return;
    }
    self.addressArr = [NSMutableArray array];
    self.loadLoctaionListDataStaus = BGLoadLoctaionListDataStausProcessing;
    self.loadLoctaionListDataTime = (long long)[[NSDate date] timeIntervalSince1970];
    @weakify(self);
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        @strongify(self);
        [self loadLoctaionAddressData];
    });
}

-(void)loadLoctaionAddressData
{
    self.loadLoctaionListDataStaus = BGLoadLoctaionListDataStausProcessing;
    self.loadLoctaionListDataTime = (long long)[[NSDate date] timeIntervalSince1970];
    NSString *path= [self getDataDirectory];
    if(!isCommonUnitEmptyString(path))
    {
        path = [path stringByAppendingPathComponent:sAddressData];
    }
    
    NSFileManager* fm = [NSFileManager defaultManager];
    NSArray *dirArray1 = [fm contentsOfDirectoryAtPath:path error:nil];
//    NSLog(@"dirarray1:%@ ",dirArray1);
    NSMutableArray *tempAddressArr1 = [NSMutableArray array];
    if(!isCommonUnitEmptyArray(dirArray1))
    {
        for(NSString *fileName in dirArray1)
        {
            if(!isCommonUnitEmptyString(fileName))
            {
                NSString *filePath1 = [path stringByAppendingPathComponent:fileName];
                NSArray *array1 = [fileName componentsSeparatedByString:@"-"];
                if (array1.count==2 || array1.count==3)
                {
                    NSString *name = array1[0];
                    NSString *code = array1[1];
                    NSString *pcode = [array1 objectAtSafeIndex:2];
                    
                    BGChinaAddressEntity *chinaAddressEntity1 = [[BGChinaAddressEntity alloc] updateWithName:name code:code pcode:pcode subFilePath:filePath1];
                    [tempAddressArr1 addObject:chinaAddressEntity1];
                    if([self isDirectory:filePath1])
                    {
                        chinaAddressEntity1.subFilePath = filePath1;
                        NSArray *dirArray2 = [fm contentsOfDirectoryAtPath:filePath1 error:nil];
                        if(!isCommonUnitEmptyArray(dirArray2))
                        {
                            NSMutableArray *tempAddressArr2 = [NSMutableArray array];
                            for(NSString *fileName2 in dirArray2)
                            {
                                if(!isCommonUnitEmptyString(fileName2))
                                {
                                    NSString *filePath2 = [filePath1 stringByAppendingPathComponent:fileName2];
                                    NSArray *array2 = [fileName2 componentsSeparatedByString:@"-"];
                                    if (array2.count==2 || array2.count==3)
                                    {
                                        NSString *name = array2[0];
                                        NSString *code = array2[1];
                                        NSString *pcode = nil;//[array2 objectAtSafeIndex:2];
                                        if(array2.count == 3)
                                        {
                                            pcode = array2[1];
                                            code = [array2 objectAtSafeIndex:2];
                                        }
                                        
                                        BGChinaAddressEntity *chinaAddressEntity2 = [[BGChinaAddressEntity alloc] updateWithName:name code:code pcode:pcode subFilePath:filePath2];
                                        [tempAddressArr2 addObject:chinaAddressEntity2];
                                        
                                        chinaAddressEntity1.sub = tempAddressArr2;
                                        if([fm fileExistsAtPath:filePath2])
                                        {
                                            NSData *data = [NSData dataWithContentsOfFile:filePath2];//读取文件
                                            NSMutableArray *arr = [NSKeyedUnarchiver unarchiveObjectWithData:data];//反序列化
                                            if(!isCommonUnitEmptyArray(arr))
                                            {
                                                chinaAddressEntity2.sub = arr;
                                            }
                                        }
                                    }
                                }
                                
                            }
                        }
                        
                        
                    }
                }
            }
            
        }
    }
    if(!isCommonUnitEmptyArray(tempAddressArr1))
    {
        [[PPSingleObject sharedInstance].addressArr removeAllObjects];
        NSArray *dirArray1 = [tempAddressArr1 sortedArrayUsingComparator:^NSComparisonResult(BGChinaAddressEntity *obj1,BGChinaAddressEntity *obj2) {
            return [obj1.code compare:obj2.code options:NSNumericSearch];//正序
        }];
//        for(BGChinaAddressEntity *chinaAddressEntity in dirArray1)
//        {
//            [[PPSingleObject sharedInstance].addressArr addObject:chinaAddressEntity];
//        }
        for(BGChinaAddressEntity *chinaAddressEntity in dirArray1)
        {
            if(!isCommonUnitEmptyArray(chinaAddressEntity.sub))
            {
                NSArray *dirArray2 = [chinaAddressEntity.sub sortedArrayUsingComparator:^NSComparisonResult(BGChinaAddressEntity *obj1,BGChinaAddressEntity *obj2) {
                    return [obj1.code compare:obj2.code options:NSNumericSearch];//正序
                }];
                chinaAddressEntity.sub = [[NSMutableArray alloc] initWithArray:dirArray2];
            }
            [[PPSingleObject sharedInstance].addressArr addObject:chinaAddressEntity];
        }
        
    }

    self.loadLoctaionListDataStaus = BGLoadLoctaionListDataStausSuccess;
    self.loadLoctaionListDataTime = 0;//(long long)[[NSDate date] timeIntervalSince1970];
}


序列化后的省市区三级联动文件

目录
相关文章
|
1月前
|
存储 安全 Java
Java一分钟之-Java序列化与反序列化
【5月更文挑战第14天】Java序列化用于将对象转换为字节流,便于存储和网络传输。实现`Serializable`接口使类可被序列化,但可能引发隐私泄露、版本兼容性和性能问题。要避免这些问题,可使用`transient`关键字、控制`serialVersionUID`及考虑使用安全的序列化库。示例代码展示了如何序列化和反序列化对象,强调了循环引用和未实现`Serializable`的错误。理解并妥善处理这些要点对优化代码至关重要。
26 1
|
3天前
|
Java 数据安全/隐私保护 Android开发
Java基础21-读懂Java序列化和反序列化(二)
Java基础21-读懂Java序列化和反序列化(二)
5 1
|
3天前
|
XML 存储 Java
Java基础21-读懂Java序列化和反序列化(一)
Java基础21-读懂Java序列化和反序列化(一)
9 1
|
8天前
|
JSON 缓存 Java
【Java基础】 序列化和反序列化
Java中的序列化(Serialization)和反序列化(Deserialization)是将对象和字节流之间进 行相互转换的过程。这两个过程用于保存对象的状态并能够在需要时恢复这些状态。
9 1
|
23天前
使用序列化和反序列化函数archivedDataWithRootObject和unarchivedObjectOfClasses的使用和遇到问题及解决方案
使用序列化和反序列化函数archivedDataWithRootObject和unarchivedObjectOfClasses的使用和遇到问题及解决方案
21 0
|
23天前
对象数组序列化和反序列化
对象数组序列化和反序列化
19 1
|
25天前
|
Java iOS开发
iOS的数据序列化(又称持久化)的两类使用方式
iOS的数据序列化(又称持久化)的两类使用方式
25 0
|
1月前
|
存储 JSON 数据挖掘
python序列化和结构化数据详解
python序列化和结构化数据详解
23 0
|
1月前
|
存储 XML JSON
数据传输的艺术:深入探讨序列化与反序列化
数据传输的艺术:深入探讨序列化与反序列化
83 0
|
1月前
|
JSON 安全 Java
Spring Boot 序列化、反序列化
本文介绍了Spring Boot中的序列化和反序列化。Java提供默认序列化机制,通过实现Serializable接口实现对象到字节流的转换。Spring Boot默认使用Jackson处理JSON,可通过注解和配置自定义规则。然而,序列化可能引发安全问题,建议使用白名单、数据校验和安全库。最佳实践包括使用标准机制、自定义规则及注意版本控制。文章还提醒关注性能并提供了相关参考资料。
93 2