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

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

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

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

由于省市区数据超过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];
}


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

目录
相关文章
|
3月前
|
XML 存储 JSON
Twaver-HTML5基础学习(19)数据容器(2)_数据序列化_XML、Json
本文介绍了Twaver HTML5中的数据序列化,包括XML和JSON格式的序列化与反序列化方法。文章通过示例代码展示了如何将DataBox中的数据序列化为XML和JSON字符串,以及如何从这些字符串中反序列化数据,重建DataBox中的对象。此外,还提到了用户自定义属性的序列化注册方法。
50 1
|
1月前
|
JSON 数据格式 索引
Python中序列化/反序列化JSON格式的数据
【11月更文挑战第4天】本文介绍了 Python 中使用 `json` 模块进行序列化和反序列化的操作。序列化是指将 Python 对象(如字典、列表)转换为 JSON 字符串,主要使用 `json.dumps` 方法。示例包括基本的字典和列表序列化,以及自定义类的序列化。反序列化则是将 JSON 字符串转换回 Python 对象,使用 `json.loads` 方法。文中还提供了具体的代码示例,展示了如何处理不同类型的 Python 对象。
|
1月前
|
存储 安全 Java
Java编程中的对象序列化与反序列化
【10月更文挑战第22天】在Java的世界里,对象序列化和反序列化是数据持久化和网络传输的关键技术。本文将带你了解如何在Java中实现对象的序列化与反序列化,并探讨其背后的原理。通过实际代码示例,我们将一步步展示如何将复杂数据结构转换为字节流,以及如何将这些字节流还原为Java对象。文章还将讨论在使用序列化时应注意的安全性问题,以确保你的应用程序既高效又安全。
|
25天前
|
XML JSON Kubernetes
什么是 YAML?:一种简洁高效的数据序列化格式
什么是 YAML?:一种简洁高效的数据序列化格式
96 0
|
2月前
|
存储 Java
Java编程中的对象序列化与反序列化
【10月更文挑战第9天】在Java的世界里,对象序列化是连接数据持久化与网络通信的桥梁。本文将深入探讨Java对象序列化的机制、实践方法及反序列化过程,通过代码示例揭示其背后的原理。从基础概念到高级应用,我们将一步步揭开序列化技术的神秘面纱,让读者能够掌握这一强大工具,以应对数据存储和传输的挑战。
|
2月前
|
存储 安全 Java
Java编程中的对象序列化与反序列化
【10月更文挑战第3天】在Java编程的世界里,对象序列化与反序列化是实现数据持久化和网络传输的关键技术。本文将深入探讨Java序列化的原理、应用场景以及如何通过代码示例实现对象的序列化与反序列化过程。从基础概念到实践操作,我们将一步步揭示这一技术的魅力所在。
|
1月前
|
存储 缓存 NoSQL
一篇搞懂!Java对象序列化与反序列化的底层逻辑
本文介绍了Java中的序列化与反序列化,包括基本概念、应用场景、实现方式及注意事项。序列化是将对象转换为字节流,便于存储和传输;反序列化则是将字节流还原为对象。文中详细讲解了实现序列化的步骤,以及常见的反序列化失败原因和最佳实践。通过实例和代码示例,帮助读者更好地理解和应用这一重要技术。
44 0
|
3月前
|
JSON 安全 编译器
扩展类实例的序列化和反序列化
扩展类实例的序列化和反序列化
43 1
|
3月前
|
存储 XML JSON
用示例说明序列化和反序列化
用示例说明序列化和反序列化
24 1
|
4月前
|
存储 Java
【IO面试题 四】、介绍一下Java的序列化与反序列化
Java的序列化与反序列化允许对象通过实现Serializable接口转换成字节序列并存储或传输,之后可以通过ObjectInputStream和ObjectOutputStream的方法将这些字节序列恢复成对象。