实时动态实现省市区三级联动选择器

简介: 实时动态实现省市区三级联动选择器

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

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

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

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

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

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

我们需要对获取的后台三级链表数据进行排序和对象化后进行序列化。应用启动时进行反序列化。

结合《省市区三级联动后台接口调用与数据预处理》和《省市区三级联动数据本地序列化和反序列化》。来实现省市区三级联动选择器。

BGChinaAddressModel.h

##import <UIKit/UIKit.h>


@interface BGChinaAddressModel : NSObject

@property (nonatomic, strong) NSString *province;
@property (nonatomic, strong) NSString *city;
@property (nonatomic, strong) NSString *district;

@end

BGChinaAddressModel.m

#import "BGChinaAddressModel.h"


@implementation BGChinaAddressModel

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

@end

BGAddressPickerView.h

#import <UIKit/UIKit.h>
#import "BGPopPicker.h"

@class BGAddressPickerView, BGChinaAddressModel;

@interface BGAddressPickerView : UIView
@property (nonatomic, strong) UIColor *selectColor;
@property (nonatomic, strong) NSMutableArray *addressArr;

-(id)initWithAddressArr:(NSMutableArray *)addressArr;
-(void)show;
@property(nonatomic, copy)void(^sendAddressBlock)(BGChinaAddressModel *address);

@end

BGAddressPickerView.m

#import "BGAddressPickerView.h"


#define kDatePickerBackViewHeight 0.3 * kUIScreenHeight + 50
#define kDatePickerHeight 0.3 * kUIScreenHeight
#define kAnimationDuration 0.25

#define kButtonWidth 60
#define kButtonHeight kDatePickerBackViewHeight - kDatePickerHeight

#define kItemHeight 40

@interface BGAddressPickerView ()<BGPopPickerDataSouce, BGPopPickerDelegate>

@property (nonatomic, weak)BGPopPicker *pickView;
@property (nonatomic, weak) UIView *pickBackView;
@property (nonatomic, strong)BGChinaAddressModel *currentAddress;

@end


@implementation BGAddressPickerView
-(id)initWithAddressArr:(NSMutableArray *)addressArr{
    if (self = [super init]) {
        self.addressArr = addressArr;
        self.frame = CGRectMake(0, 0, kUIScreenWidth, kUIScreenHeight);
        self.backgroundColor = [UIColor colorWithRed:0.0 green:0.0 blue:0.0 alpha:0.5f];
        self.userInteractionEnabled = YES;
        UITapGestureRecognizer *cancelGesture = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(cancelBtnClicked)];
        [self addGestureRecognizer:cancelGesture];
        [self setupSubViews];
    }
    return self;
}
- (void)show
{
    @weakify(self);
    [[UIApplication sharedApplication].keyWindow addSubview:self];
    [UIView animateWithDuration:kAnimationDuration animations:^{
        @strongify(self);
        self.alpha = 1;
        CGFloat modifyY = kUIScreenHeight - kDatePickerBackViewHeight;
        self.pickBackView.frame = CGRectMake(0, modifyY, kUIScreenWidth, kDatePickerBackViewHeight);
    }];
}

-(void)setupSubViews{    
    BGPopPicker *picker = [[BGPopPicker alloc]initWithAddressArr:self.addressArr];
    picker.delegate = self;
    picker.dataSource = self;
    @weakify(self);
    picker.cancelBtnClickBlock = ^(){
        @strongify(self);
        [self cancelBtnClicked];
    };
    picker.doneBtnClickBlock = ^(){
        @strongify(self);
        [self actionDone];
    };
//    self.currentAddress = [BGChinaAddressModel mj_objectWithKeyValues:picker.currentAddress];
    self.currentAddress = picker.currentAddress;
    self.currentAddress.province = picker.currentAddress.province;
    self.currentAddress.city = picker.currentAddress.city;
    self.currentAddress.district = picker.currentAddress.district;
    [self addSubview:picker];
    [picker showAddressPicker];
    self.pickView = picker;
}



//点击确定
-(void)actionDone{
    if (self.sendAddressBlock) {
        self.sendAddressBlock(self.currentAddress);
    }
    [self performSelector:@selector(cancelBtnClicked) withObject:nil afterDelay:0.2];
}
//点击取消
- (void)cancelBtnClicked
{
    @weakify(self);
    [UIView animateWithDuration:kAnimationDuration animations:^{
        @strongify(self);
        self.alpha = 0;
        self.pickBackView.frame = CGRectMake(0, kUIScreenHeight, kUIScreenWidth, kDatePickerBackViewHeight);
    } completion:^(BOOL finished) {
        @strongify(self);
        [self removeFromSuperview];
    }];
}

#pragma mark - BGPopPickerDataSouce, BGPopPickerDelegate

- (NSInteger)numberOfComponentsInPickerView:(BGPopPicker *)popPicker{
    return 1;
}
- (NSInteger)popPicker:(BGPopPicker *)popPicker numberOfRowsInComponent:(NSInteger)component{
    return 10;
}
-(void)popPicker:(BGPopPicker *)popPicker didSelectedAddress:(BGChinaAddressModel *)address{
    self.currentAddress = address;
}
-(void)backViewTapWithNoAction
{//should do nothing here
    
}

-(void)setSelectColor:(UIColor *)selectColor
{
    self.pickView.selectColor = selectColor;
}
@end

BGPopPicker.h

#import <UIKit/UIKit.h>
#import "BGChinaAddressEntity.h"
#import "BGChinaAddressModel.h"

typedef NS_ENUM(NSInteger, BGPopPickerType) {
    BGPopPickerTypeDefault = 0,   // picer view with no data,
    BGPopPickerTypeAddress,       // address picker view
    BGPopPickerTypeTime,          // date picker view
};

@class BGPopPicker;
@protocol BGPopPickerDataSouce <NSObject>

@optional

- (NSInteger)numberOfComponentsInPickerView:(BGPopPicker *)popPicker;
- (NSInteger)popPicker:(BGPopPicker *)popPicker numberOfRowsInComponent:(NSInteger)component;

@end



@protocol BGPopPickerDelegate <NSObject>

@optional

// returns width of column and height of row for each component.
- (CGFloat)popPicker:(BGPopPicker *)popPicker widthForComponent:(NSInteger)component;
- (CGFloat)popPicker:(BGPopPicker *)popPicker rowHeightForComponent:(NSInteger)component;
- (UIView *)popPicker:(BGPopPicker *)popPicker viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(UIView *)view;
- (void)popPicker:(BGPopPicker *)popPicker didSelectedAddress:(BGChinaAddressModel *)address;
- (void)popPicker:(BGPopPicker *)popPicker didSelectedHour:(NSString *)hour mimute:(NSString *)minute;


// button action
- (void)cancelAction;
- (void)doneAction;

@end



@interface BGPopPicker : UIView

@property (nonatomic, assign, readonly) BOOL isShow;           //  default is NO, picker view show

//>>>>>>>>>>>>>>>>>自己添加的>>>>>>>>>>>>>>>>>>>>>>

@property (nonatomic, copy)void(^cancelBtnClickBlock)();
@property (nonatomic, copy)void(^doneBtnClickBlock)();
-(BGChinaAddressModel *)currentAddress;
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

@property (nonatomic, assign) id <BGPopPickerDataSouce> dataSource;
@property (nonatomic, assign) id <BGPopPickerDelegate> delegate;

// used to set begin time, default is 00:00
@property (nonatomic, assign) NSInteger hour;    // hour from 0 to 23, otherwise equal 0
@property (nonatomic, assign) NSInteger minute;  // minute from 0 to 59, otherwise euqal 0

@property (nonatomic, strong) UIColor *selectColor;
@property (nonatomic, strong) NSMutableArray *addressArr;

- (void)showDefaultPicker;   // show picker view with no content
- (void)showAddressPicker;   // show picker view with china address
- (void)showDatePicker;      // show picker view with time,format HH:mm

-(id)initWithAddressArr:(NSMutableArray *)addressArr;
@end

BGPopPicker.m

#import "BGPopPicker.h"

static CGFloat BGPopPickerHeightFactor = 0.5;
static CGFloat BGPopPickerTitleViewHeight  = 50;
static CGFloat BGPopPickerTitleLabelWidth = 200;
static CGFloat BGPopPickerButtonWidth = 70;


#define UISCREEN_HEIGHT [[UIScreen mainScreen] bounds].size.height
#define UISCREEN_WIDTH  [[UIScreen mainScreen] bounds].size.width

typedef NS_ENUM(NSInteger, AddressType) {
    AddressTypeProvince = 0,
    AddressTypeCity     = 1,
    AddressTypeDistrict = 2
    
};

@interface BGPopPicker()<UIPickerViewDataSource, UIPickerViewDelegate>

@property (nonatomic, strong) UIView *titleView;
@property (nonatomic, strong) UILabel *titleLabel;
@property (nonatomic, strong) UIButton *cancelButton;
@property (nonatomic, strong) UIButton *doneButton;

// picker view
@property (nonatomic, strong) UIPickerView *defaultPickerView;
@property (nonatomic, strong) UIPickerView *addressPickerView;
@property (nonatomic, strong) UIPickerView *datePickerView;

// address Data
@property (nonatomic, strong) NSDictionary *addressDictionary;
@property (nonatomic, strong) NSString *currentProvince;

@property (nonatomic, strong) BGChinaAddressEntity *currentProvinceEntity;
@property (nonatomic, strong) BGChinaAddressEntity *currentCityEntity;
@property (nonatomic, strong) BGChinaAddressEntity *currentDistrictEntity;

@property (nonatomic, strong) NSDictionary *currentDictionary;  // 当前选中的城市字典包含省市县
@property (strong, nonatomic) NSMutableArray *province;  // 省
@property (strong, nonatomic) NSMutableArray *city;      // 市
@property (strong, nonatomic) NSMutableArray *district;  // 县


// Date data
@property (nonatomic, strong) NSMutableArray *hoursArray;
@property (nonatomic, strong) NSMutableArray *minutesArray;

@end


@implementation BGPopPicker

- (instancetype)initWithAddressArr:(NSMutableArray *)addressArr
{
    self = [super init];
    if (self) {
        self.addressArr = addressArr;
        NSLog(@"addressArr:%@", addressArr);
        self.frame = CGRectMake(0, UISCREEN_HEIGHT, UISCREEN_WIDTH, UISCREEN_HEIGHT*BGPopPickerHeightFactor);
        self.backgroundColor = [UIColor whiteColor];
        [self loadAddress];  // 加载地址
        [self configureDate];       // 日期数据
    }
    return self;
}

- (instancetype)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        
    }
    return self;
}

-(BGChinaAddressModel *)currentAddress{
    BGChinaAddressModel *address = [[BGChinaAddressModel alloc] init];
    if (_currentProvinceEntity && [_currentProvinceEntity isKindOfClass:[BGChinaAddressEntity class]] && _currentCityEntity && [_currentCityEntity isKindOfClass:[BGChinaAddressEntity class]] && _currentDistrictEntity && [_currentDistrictEntity isKindOfClass:[BGChinaAddressEntity class]]) {
        address.province = _currentProvinceEntity.name;
        address.city = _currentCityEntity.name;
        address.district = _currentDistrictEntity.name;
    }
//    if (_currentDictionary) {
//        address.province = [_currentDictionary objectForKey:@"gldprovince"];
//        address.city = [_currentDictionary objectForKey:@"gldcity"];
//        address.district = [_currentDictionary objectForKey:@"glddistrict"];
//    }
    return address;
}

#pragma mark -  Action

- (void)cancelButtonOnClick
{
    [self dismiss];
    if ([_delegate respondsToSelector:@selector(cancelAction)]) {
        [_delegate cancelAction];
    }
    if (self.cancelBtnClickBlock) {
        self.cancelBtnClickBlock();
    }
}

- (void)doneButtonOnClick
{
    [self dismiss];
    if ([_delegate respondsToSelector:@selector(doneAction)]) {
        [_delegate doneAction];
    }
    if (self.doneBtnClickBlock) {
        self.doneBtnClickBlock();
    }
}


#pragma mark - Private Method

- (void)drawRect:(CGRect)rect {
    
    UIView *titleView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, [[UIScreen mainScreen] bounds].size.width, BGPopPickerTitleViewHeight)];
//    UIView *titleView = [[UIView alloc] initWithFrame:self.bounds];
    titleView.backgroundColor = [UIColor groupTableViewBackgroundColor];
    
    UILabel *titleLabel = [[UILabel alloc] initWithFrame:CGRectMake(self.frame.size.width / 2 - BGPopPickerTitleLabelWidth / 2, 0, BGPopPickerTitleLabelWidth, BGPopPickerTitleViewHeight)];
    titleLabel.textAlignment = NSTextAlignmentCenter;
    
    UIFont *font = [UIFont systemFontOfSize:16.0f];
    titleLabel.font = font;
    titleLabel.textColor = [UIColor whiteColor];
    //[titleLabel sizeToFit];
    _titleLabel = titleLabel;
    _titleView = titleView;
    
    [titleView addSubview:_titleLabel];
    
    // cancel button
    CGFloat buttonOffset = 0.0f;
    UIButton *leftButton = [UIButton buttonWithType:UIButtonTypeCustom];
    leftButton.frame = CGRectMake(buttonOffset, 0, BGPopPickerButtonWidth, BGPopPickerTitleViewHeight);
    [leftButton setTitle:@"取消" forState:UIControlStateNormal];
    [leftButton setTitleColor:[UIColor colorWithRed:0.5 green:0.5 blue:0.5 alpha:1] forState:UIControlStateNormal];
    leftButton.contentHorizontalAlignment = UIControlContentHorizontalAlignmentCenter;
    leftButton.titleLabel.font = font;
    [leftButton addTarget:self action:@selector(cancelButtonOnClick) forControlEvents:UIControlEventTouchUpInside];
    _cancelButton = leftButton;
    [titleView addSubview:_cancelButton];
    
    // done button
    UIButton *rightButton = [UIButton buttonWithType:UIButtonTypeCustom];
    rightButton.frame = CGRectMake(self.frame.size.width - BGPopPickerButtonWidth - buttonOffset, 0, BGPopPickerButtonWidth, BGPopPickerTitleViewHeight);
    [rightButton setTitle:@"确定" forState:UIControlStateNormal];
    [rightButton setTitleColor:[UIColor colorWithRed:255.0f/255.0f green:121.0f/255.0f blue:76.0f/255.0f alpha:1] forState:UIControlStateNormal];
    rightButton.contentHorizontalAlignment = UIControlContentHorizontalAlignmentCenter;
    rightButton.titleLabel.font = font;
    [rightButton addTarget:self action:@selector(doneButtonOnClick) forControlEvents:UIControlEventTouchUpInside];
    _doneButton = rightButton;
    [titleView addSubview:_doneButton];
    
    [self addSubview:_titleView];
    
    [self createPickerView];  // 创建picker view
    

}

- (void)createPickerView
{
    UIPickerView *addressPickerView = [[UIPickerView alloc] initWithFrame:CGRectMake(0, _titleView.frame.size.height, UISCREEN_WIDTH, BGPopPickerHeightFactor*UISCREEN_HEIGHT)];
    addressPickerView.backgroundColor = [UIColor whiteColor];
    addressPickerView.delegate = self;
    addressPickerView.dataSource = self;
    addressPickerView.tag = 1;
    _addressPickerView = addressPickerView;
    [self addSubview:addressPickerView];
}
// 加载地址信息
- (void)loadAddress
{
    if(self.province && [self.province isKindOfClass:[NSArray class]])
    {
        [self.province removeAllObjects];
    }
    else
    {
        self.province = [NSMutableArray array];
    }
    for(BGChinaAddressEntity *entity1 in self.addressArr)
    {
        if(entity1 && [entity1 isKindOfClass:[BGChinaAddressEntity class]])
        {
//            BGChinaAddressEntity *entity1 = [BGChinaAddressEntity mj_objectWithKeyValues:dic1];
//            [self.model.addressArr addSafeObject:entity1];
            NSMutableArray *sub1 = entity1.sub;
            if(!isCommonUnitEmptyArray(sub1))
            {
//                NSMutableArray *sub3 = [NSMutableArray  array];
                for(BGChinaAddressEntity *entity2 in sub1)
                {
//                    BGChinaAddressEntity *entity2 = [BGChinaAddressEntity mj_objectWithKeyValues:dic2];
//                    [sub3 addSafeObject:entity2];
                    if(entity2 && [entity2 isKindOfClass:[BGChinaAddressEntity class]])
                    {
                        NSMutableArray *sub2 = entity2.sub;
                        if(!isCommonUnitEmptyArray(sub2))
                        {
//                            NSMutableArray *sub4 = [BGChinaAddressEntity mj_objectArrayWithKeyValuesArray:sub2];
//                            NSArray*sortedArray = [sub4 sortedArrayUsingComparator:^NSComparisonResult(BGChinaAddressEntity *obj1,BGChinaAddressEntity *obj2) {
//                                return [obj1.code compare:obj2.code options:NSNumericSearch];//正序
//                            }];
//                            entity2.sub = [[NSMutableArray alloc] initWithArray:sortedArray];
//                            if(entity2.sub.count == 26 || entity2.sub.count == 24 || entity2.sub.count == 22)
//                            {
//                                NSLog(@"entity2.sub:%d,entity2.name:%@", entity2.sub.count, entity2.name);
//                            }
//                            NSLog(@"entity2.sub:%d", entity2.sub.count);
                        }
                    }
                }
//                if(!isCommonUnitEmptyArray(sub3))
//                {
//                    NSArray*sortedArray = [sub3 sortedArrayUsingComparator:^NSComparisonResult(BGChinaAddressEntity *obj1,BGChinaAddressEntity *obj2) {
//                        return [obj1.code compare:obj2.code options:NSNumericSearch];//正序
//                    }];
//                    entity1.sub = [[NSMutableArray alloc] initWithArray:sortedArray];
//                    NSLog(@"entity1.sub:%d", entity1.sub.count);
//                }
                
                [self.province addSafeObject:entity1];
            }
        }
    }
     
    _currentProvinceEntity =[_province firstObject];
    _currentCityEntity = [_currentProvinceEntity.sub firstObject];
    _currentDistrictEntity = [_currentCityEntity.sub firstObject];
    NSLog(@"%@,%@", _currentDistrictEntity, _currentDistrictEntity.name);
    NSLog(@"%@,%@", _currentDistrictEntity, _currentDistrictEntity.name);
}
// 加载地址信息
- (void)loadAddressMessage
{
    NSArray*sortedArray = [self.addressArr sortedArrayUsingComparator:^NSComparisonResult(NSDictionary *obj1,NSDictionary *obj2) {
        return [obj1[@"code"] compare:obj2[@"code"] options:NSNumericSearch];//正序
    }];
    if(self.province && [self.province isKindOfClass:[NSArray class]])
    {
        [self.province removeAllObjects];
    }
    else
    {
        self.province = [NSMutableArray array];
    }
    for(NSDictionary *dic1 in sortedArray)
    {
        if(!isCommonUnitEmptyDict(dic1))
        {
            BGChinaAddressEntity *entity1 = [BGChinaAddressEntity mj_objectWithKeyValues:dic1];
            NSMutableArray *sub1 = dic1[@"sub"];
            if(!isCommonUnitEmptyArray(sub1))
            {
                NSMutableArray *sub3 = [NSMutableArray  array];
                for(NSDictionary *dic2 in sub1)
                {
                    BGChinaAddressEntity *entity2 = [BGChinaAddressEntity mj_objectWithKeyValues:dic2];
                    [sub3 addSafeObject:entity2];
                    if(!isCommonUnitEmptyDict(dic2))
                    {
                        NSMutableArray *sub2 = dic2[@"sub"];
                        if(!isCommonUnitEmptyArray(sub2))
                        {
                            NSMutableArray *sub4 = [BGChinaAddressEntity mj_objectArrayWithKeyValuesArray:sub2];
                            NSArray*sortedArray = [sub4 sortedArrayUsingComparator:^NSComparisonResult(BGChinaAddressEntity *obj1,BGChinaAddressEntity *obj2) {
                                return [obj1.code compare:obj2.code options:NSNumericSearch];//正序
                            }];
                            entity2.sub = [[NSMutableArray alloc] initWithArray:sortedArray];
                        }
                    }
                }
                if(!isCommonUnitEmptyArray(sub3))
                {
                    NSArray*sortedArray = [sub3 sortedArrayUsingComparator:^NSComparisonResult(BGChinaAddressEntity *obj1,BGChinaAddressEntity *obj2) {
                        return [obj1.code compare:obj2.code options:NSNumericSearch];//正序
                    }];
                    entity1.sub = [[NSMutableArray alloc] initWithArray:sortedArray];
                }
                
                [self.province addSafeObject:entity1];
            }
        }
    }
    
    
//    NSString *index = [sortedArray objectAtSafeIndex:0];
//    NSString *selected = [_province objectAtSafeIndex:0];
//    NSDictionary *dic = [NSDictionary dictionaryWithDictionary: [[addressDictionary objectForKey:index]objectForKey:selected]];
//
//    NSArray *cityArray = [dic allKeys];
//    NSDictionary *cityDic = [NSDictionary dictionaryWithDictionary: [dic objectForKey: [cityArray objectAtSafeIndex:0]]];
//    _city = [[NSArray alloc] initWithArray: [cityDic allKeys]];

    _currentProvinceEntity =[_province firstObject];
    _currentCityEntity = [_currentProvinceEntity.sub firstObject];
    _currentDistrictEntity = [_currentCityEntity.sub firstObject];
    NSLog(@"%@,%@", _currentDistrictEntity, _currentDistrictEntity.name);
    NSLog(@"%@,%@", _currentDistrictEntity, _currentDistrictEntity.name);

//    NSString *selectedCity = [_city objectAtSafeIndex: 0];
//    _district = [[NSArray alloc] initWithArray: [cityDic objectForKey: selectedCity]];
//
//    _currentDictionary = @{@"gldprovince" : [_province firstObject], @"gldcity" : [_city firstObject], @"glddistrict" : [_district firstObject]};
    
//    NSBundle *bundle = [NSBundle mainBundle];
//    NSString *plistPath = [bundle pathForResource:@"chinaAddress" ofType:@"plist"];
//
//    NSDictionary *addressDictionary = [[NSDictionary alloc] initWithContentsOfFile:plistPath];
//    _addressDictionary = addressDictionary;
//    NSArray *components = [addressDictionary allKeys];
//
//    NSArray *sortedArray = [components sortedArrayUsingComparator: ^(id obj1, id obj2) {
//
//        if ([obj1 integerValue] > [obj2 integerValue]) {
//            return (NSComparisonResult)NSOrderedDescending;
//        }
//
//        if ([obj1 integerValue] < [obj2 integerValue]) {
//            return (NSComparisonResult)NSOrderedAscending;
//        }
//        return (NSComparisonResult)NSOrderedSame;
//    }];
//
//    NSMutableArray *provinceTmp = [[NSMutableArray alloc] init];
//    for (int i=0; i<[sortedArray count]; i++) {
//        NSString *index = [sortedArray objectAtSafeIndex:i];
//        NSArray *tmp = [[addressDictionary objectForKey: index] allKeys];
//        [provinceTmp addObject: [tmp objectAtSafeIndex:0]];
//    }
//
//    _province = [[NSArray alloc] initWithArray:provinceTmp];
//
//    NSString *index = [sortedArray objectAtSafeIndex:0];
//    NSString *selected = [_province objectAtSafeIndex:0];
//    NSDictionary *dic = [NSDictionary dictionaryWithDictionary: [[addressDictionary objectForKey:index]objectForKey:selected]];
//
//    NSArray *cityArray = [dic allKeys];
//    NSDictionary *cityDic = [NSDictionary dictionaryWithDictionary: [dic objectForKey: [cityArray objectAtSafeIndex:0]]];
//    _city = [[NSArray alloc] initWithArray: [cityDic allKeys]];
//
//
//    NSString *selectedCity = [_city objectAtSafeIndex: 0];
//    _district = [[NSArray alloc] initWithArray: [cityDic objectForKey: selectedCity]];
//
//    _currentDictionary = @{@"gldprovince" : [_province firstObject], @"gldcity" : [_city firstObject], @"glddistrict" : [_district firstObject]};
    

}

// 配置时间数据
- (void)configureDate
{
    NSMutableArray *hoursArray = [[NSMutableArray alloc] init];
    NSMutableArray *minutesArray = [[NSMutableArray alloc] init];
    for (NSInteger h=0; h<24; ++h) {
        [hoursArray addObject:[NSString stringWithFormat:@"%02ld",(long)h]];
    }
    _hoursArray = hoursArray;
    _hour = 0;
    
    
    for (NSInteger m=0; m<60; ++m) {
        [minutesArray addObject:[NSString stringWithFormat:@"%02ld",(long)m]];
    }
    _minutesArray = minutesArray;
    _minute = 0;
}

- (UILabel *)createCommonLabelForComponents
{
    UILabel *commonLabel = [[UILabel alloc] init];
    commonLabel.frame = CGRectMake(0, 0, 100, 30);
    commonLabel.textAlignment = NSTextAlignmentCenter;
    commonLabel.font = [UIFont systemFontOfSize:14];
    commonLabel.backgroundColor = [UIColor clearColor];
    
    return commonLabel;
}

#pragma mark -

- (BOOL)show
{
    if (_isShow) {
        return _isShow;
    }
    @weakify(self);
    _isShow = YES;
    CGRect showFrame = self.frame;
    showFrame.origin.y = showFrame.origin.y - self.frame.size.height;
    [UIView animateWithDuration:0.3f animations:^{
        @strongify(self);
        self.frame = showFrame;
    }];
    return _isShow;
}

- (BOOL)dismiss
{
    if (!_isShow) {
        return _isShow;
    }

    @weakify(self);
    _isShow = NO;
    CGRect hideFrame = self.frame;
    hideFrame.origin.y = hideFrame.origin.y  + self.frame.size.height;
    [UIView animateWithDuration:0.3f animations:^{
        @strongify(self);
        self.frame = hideFrame;
    }];
    return _isShow;
}

#pragma mark - Public Method

- (void)showDefaultPicker
{
    BOOL show = [self show];
    if (show) {
        [self sendSubviewToBack:_datePickerView];
        [self sendSubviewToBack:_addressPickerView];
    }
}

- (void)showAddressPicker
{
    BOOL show = [self show];
    if (show) {
        [self sendSubviewToBack:_datePickerView];
        [self sendSubviewToBack:_defaultPickerView];
    }
}

- (void)showDatePicker
{
    BOOL show = [self show];
    if (show) {
        
        if (_hour > 23 && _hour < 0) {
            _hour = 0;
        }
        if (_minute > 59 && _minute < 0) {
            _minute = 0;
        }
        
        [_datePickerView selectRow:2400 + _hour inComponent:0 animated:YES];
        [_datePickerView selectRow:6000 + _minute inComponent:1 animated:YES];
        
        [self sendSubviewToBack:_addressPickerView];
        [self sendSubviewToBack:_defaultPickerView];
    }
}

#pragma mark - UIPicker view data source

- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView
{
    switch (pickerView.tag) {
        case BGPopPickerTypeDefault: {
            if ([_dataSource respondsToSelector:@selector(numberOfComponentsInPickerView:)]) {
                return [_dataSource numberOfComponentsInPickerView:self];
            }else {
                return 0;
            }
        }
            break;
        
        case BGPopPickerTypeAddress: {
            return 3;
        }
            break;
        
        case BGPopPickerTypeTime: {
            return 2;
        }
            break;
            
        default:
            return 0;
            break;
    }
    
}

- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component
{
    switch (pickerView.tag) {
        case BGPopPickerTypeDefault: {
            if ([_dataSource respondsToSelector:@selector(popPicker:numberOfRowsInComponent:)]) {
                return [_dataSource popPicker:self numberOfRowsInComponent:component];
            }
            return 0;
        }
            break;
      
            
        case BGPopPickerTypeAddress: {
            switch (component) {
                case 0:
                    return _province.count;
                    break;
                case 1:
                    return _currentProvinceEntity.sub.count;
//                    return _city.count;
                    break;
                case 2:
                    return _currentCityEntity.sub.count;
//                    return _district.count;
                    break;
            }
        }
            break;
            
            
        case BGPopPickerTypeTime:
            return 65536;
            break;
    }
    return 0;
}

#pragma mark - UIPicker view delegate

- (CGFloat)pickerView:(UIPickerView *)pickerView widthForComponent:(NSInteger)component
{
    switch (pickerView.tag) {
        case BGPopPickerTypeDefault: {
            
        }
            break;
        
        case BGPopPickerTypeAddress: {
            return 100;
        }
            break;
            
        case BGPopPickerTypeTime: {
            return 80;
        }
            break;
    }
    return 0;
}

- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component
{
    return nil;
}

- (UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(UIView *)view
{
    switch (pickerView.tag) {
            
        case BGPopPickerTypeDefault: {
            
            if ([_delegate respondsToSelector:@selector(popPicker:viewForRow:forComponent:reusingView:)]) {
                return [_delegate popPicker:self viewForRow:row forComponent:component reusingView:view];
            }else {
                return nil;
            }
        }
            break;
            
            
        case BGPopPickerTypeAddress: {
            
            UILabel *itemLabel = [self createCommonLabelForComponents];
            if (component == AddressTypeProvince) {
                BGChinaAddressEntity *provinceEntity = [_province objectAtSafeIndex:row];
                itemLabel.text = provinceEntity.name;
            }else if (component == AddressTypeCity) {
                BGChinaAddressEntity *cityEntity = [_currentProvinceEntity.sub objectAtSafeIndex:row];
                itemLabel.text = cityEntity.name;
            }else {
                BGChinaAddressEntity *districtEntity = [_currentCityEntity.sub objectAtSafeIndex:row];
                itemLabel.text = districtEntity.name;
            }
//            if (component == AddressTypeProvince) {
//                itemLabel.text = [_province objectAtSafeIndex:row];
//            }else if (component == AddressTypeCity) {
//                itemLabel.text = [_city objectAtSafeIndex:row];
//            }else {
//                itemLabel.text = [_district objectAtSafeIndex:row];
//            }
            return itemLabel;
        }
            break;
            
            
        case BGPopPickerTypeTime: {
            
            UILabel *dateLabel = [self createCommonLabelForComponents];
            dateLabel.font = [UIFont systemFontOfSize:22];
            if (component == 0) {
                dateLabel.text = [_hoursArray objectAtSafeIndex:row%_hoursArray.count];
            }else if (component == 1) {
                dateLabel.text = [_minutesArray objectAtSafeIndex:row%_minutesArray.count];
            }
            return dateLabel;
        }
            break;
        default:
            break;
    }
    return nil;
}

- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component
{
    switch (pickerView.tag) {
        case BGPopPickerTypeDefault: {
        }
            break;
            
        case BGPopPickerTypeAddress: {
            NSString *province = @"";
            NSString *city = @"";
            NSString *district = @"";
            if (_currentProvinceEntity && [_currentProvinceEntity isKindOfClass:[BGChinaAddressEntity class]] && _currentCityEntity && [_currentCityEntity isKindOfClass:[BGChinaAddressEntity class]] && _currentDistrictEntity && [_currentDistrictEntity isKindOfClass:[BGChinaAddressEntity class]]) {
                province = _currentProvinceEntity.name;
                city = _currentCityEntity.name;
                district = _currentDistrictEntity.name;
            }
//            NSString *province = [_currentDictionary objectForKey:@"gldprovince"];
//            NSString *city = [_currentDictionary objectForKey:@"gldcity"];
//            NSString *district = [_currentDictionary objectForKey:@"glddistrict"];
            if (component == AddressTypeProvince) {
                _currentProvinceEntity = [_province objectAtSafeIndex:row];
//                _currentProvince = [_province objectAtSafeIndex:row];
                NSMutableArray *cityArray = _currentProvinceEntity.sub;
//                NSMutableArray*sortedArray = [cityArray sortedArrayUsingComparator:^NSComparisonResult(BGChinaAddressEntity *obj1,BGChinaAddressEntity *obj2) {
//                    return [[obj1.code compare:obj2.code] options:NSNumericSearch];//正序
//                }];
//                cityArray = sortedArray;
//                NSDictionary *tmp = [NSDictionary dictionaryWithDictionary: [_addressDictionary objectForKey: [NSString stringWithFormat:@"%ld", (long)row]]];
//                NSDictionary *dic = [NSDictionary dictionaryWithDictionary: [tmp objectForKey: _currentProvince]];
//                NSArray *cityArray = [dic allKeys];
//                NSArray *sortedArray = [cityArray sortedArrayUsingComparator: ^(id obj1, id obj2) {
//
//                    if ([obj1 integerValue] > [obj2 integerValue]) {
//                        return (NSComparisonResult)NSOrderedDescending;//递减
//                    }
//
//                    if ([obj1 integerValue] < [obj2 integerValue]) {
//                        return (NSComparisonResult)NSOrderedAscending;//上升
//                    }
//                    return (NSComparisonResult)NSOrderedSame;
//                }];
                
//                NSMutableArray *array = [[NSMutableArray alloc] init];
//                for (int i=0; i<[sortedArray count]; i++) {
//                    NSString *index = [sortedArray objectAtSafeIndex:i];
//                    NSArray *temp = [[dic objectForKey: index] allKeys];
//                    [array addObject: [temp objectAtSafeIndex:0]];
//                }
//
//                _city = [[NSArray alloc] initWithArray: array];
                
//                NSDictionary *cityDic = [dic objectForKey: [sortedArray objectAtSafeIndex:0]];
//                _district = [[NSArray alloc] initWithArray: [cityDic objectForKey: [_city objectAtSafeIndex:0]]];
                
                [_addressPickerView selectRow:0 inComponent:AddressTypeCity animated:YES];
                [_addressPickerView selectRow:0 inComponent:AddressTypeDistrict animated:YES];
                [_addressPickerView reloadComponent:AddressTypeCity];
                [_addressPickerView reloadComponent:AddressTypeDistrict];
                
//                province = [_province objectAtSafeIndex:row];
//                city = [_city objectAtSafeIndex:0];
//                district = [_district objectAtSafeIndex:0];
                
                
                _currentCityEntity = [_currentProvinceEntity.sub firstObject];
                _currentDistrictEntity = [_currentCityEntity.sub firstObject];
                
                province = _currentProvinceEntity.name;
                city = _currentCityEntity.name;
                district = _currentDistrictEntity.name;
            }
            else if (component == AddressTypeCity) {
                _currentCityEntity = [_currentProvinceEntity.sub objectAtSafeIndex:row];
                if (_currentProvinceEntity.sub.count == 0) {
                    _currentDistrictEntity = nil;
                    return;
                }else{
                    _currentDistrictEntity = [_currentCityEntity.sub objectAtSafeIndex:0];
                    [_addressPickerView selectRow: 0 inComponent: AddressTypeDistrict animated: YES];
                    [_addressPickerView reloadComponent:AddressTypeDistrict];
                }
//                city = [_city objectAtSafeIndex:row];
                district = _currentDistrictEntity.name;
                
//                NSString *provinceIndex = [NSString stringWithFormat: @"%ld", (unsigned long)[_province indexOfObject: _currentProvince]];
//                NSDictionary *tmp = [NSDictionary dictionaryWithDictionary: [_addressDictionary objectForKey: provinceIndex]];
//                NSDictionary *dic = [NSDictionary dictionaryWithDictionary: [tmp objectForKey:_currentProvince]];
//                NSArray *dicKeyArray = [dic allKeys];
//                NSArray *sortedArray = [dicKeyArray sortedArrayUsingComparator: ^(id obj1, id obj2) {
//                    if ([obj1 integerValue] > [obj2 integerValue]) {
//                        return (NSComparisonResult)NSOrderedDescending;
//                    }
//
//                    if ([obj1 integerValue] < [obj2 integerValue]) {
//                        return (NSComparisonResult)NSOrderedAscending;
//                    }
//                    return (NSComparisonResult)NSOrderedSame;
//                }];
//                if (sortedArray.count == 0) {
//                    return;
//                }else{
//                    NSDictionary *cityDic = [NSDictionary dictionaryWithDictionary: [dic objectForKey: [sortedArray objectAtSafeIndex: row]]];
//                    NSArray *cityKeyArray = [cityDic allKeys];
//
//                    _district = [[NSArray alloc] initWithArray: [cityDic objectForKey: [cityKeyArray objectAtSafeIndex:0]]];
//                    [_addressPickerView selectRow: 0 inComponent: AddressTypeDistrict animated: YES];
//                    [_addressPickerView reloadComponent:AddressTypeDistrict];
//                }
//                city = [_city objectAtSafeIndex:row];
//                district = [_district objectAtSafeIndex:0];
                
            }else if (component == AddressTypeDistrict) {
                
//                district = [_district objectAtSafeIndex:row];
                _currentDistrictEntity = [_currentCityEntity.sub objectAtSafeIndex:row];
                district = _currentDistrictEntity.name;
            }
            
//            NSDictionary *addDic = @{@"gldprovince" : province , @"gldcity" : city, @"glddistrict" : district };
//            _currentDictionary = addDic;

            if ([_delegate respondsToSelector:@selector(popPicker:didSelectedAddress:)]) {
                BGChinaAddressModel *addressModel = [[BGChinaAddressModel alloc] init];
                addressModel.province = province;
                addressModel.city = city;
                addressModel.district  = district;
                [_delegate popPicker:self didSelectedAddress:addressModel];
            }
        }
            break;
            
        case BGPopPickerTypeTime: {
            
            if (component == 0) {
                _hour = [[_hoursArray objectAtSafeIndex:row%_hoursArray.count] integerValue];
            }else if (component == 1) {
                _minute = [[_minutesArray objectAtSafeIndex:row%_minutesArray.count] integerValue];
            }
            
            if ([_delegate respondsToSelector:@selector(popPicker:didSelectedHour:mimute:)]) {
                NSString *hour = [NSString stringWithFormat:@"%02ld",(long)_hour];
                NSString *minute = [NSString stringWithFormat:@"%02ld",(long)_minute];
                [_delegate popPicker:self didSelectedHour:hour mimute:minute];
            }
        }
            break;
        default:
            break;
    }
}

-(void)setSelectColor:(UIColor *)selectColor
{
    [_doneButton setTitleColor:selectColor forState:UIControlStateNormal];
}

@end

目录
相关文章
|
JavaScript Java 数据库连接
省市区 - 三级联动通用化模块组件
都说我们要做模块化设计,而不要做功能化设计 什么是模块化设计,就是可插拔性高,组件化,想要就用,不要用拉倒,直接删除就行 什么是功能化设计,就是一个简单的功能,实现想要的效果,但是不够通用化,别人要用的话需要读懂你的代码,还需要复制黏贴很多代码这样效率不高   今天写了一个省市区三级联动的模...
1555 0
|
C# 数据格式 JSON
常用省市区无刷新联动实例
1、jquery代码 function getCity(CityVal) { var DDL_Province = $("#DDL_Province"); var DDL_City = $("#DDL_City"); DDL_City.
704 0
|
7月前
|
JavaScript
原生js实现省市区三级联动
原生js实现省市区三级联动
68 0
|
7月前
|
SQL 缓存 JSON
vue利用级联选择器实现全国省市区乡村五级菜单联动
vue利用级联选择器实现全国省市区乡村五级菜单联动
|
JavaScript 前端开发
仿百度文库文档上传页面的多级联动分类选择器
仿百度文库文档上传页面的多级联动分类选择器 下载地址:http://download.csdn.net/detail/testcs_dn/6848547,下载后评论,积分会返还的。 最终效果图: 使用示例代码: category $(document).
787 0
|
7月前
|
小程序 前端开发
实现微信小程序picker 省市区 自定义数据 支持三级联动
实现微信小程序picker 省市区 自定义数据 支持三级联动
196 0
|
JavaScript
jQuery多级联动美化版Select下拉框
在线演示 本地下载
1264 0