省市区选择组件实践-2020-04-21

2020-04-24  本文已影响0人  勇往直前888

简介

一般省市区的选择组件采用UIPickerView来实现,比如这篇文章就很好iOS-省市区选择的实现
。这次为了和Android保持风格一致,采用自定义视图的方式。大概的样子如下:

企业微信截图_400eb34d-1d9d-43de-ad6b-e2aebee15993.png

数据源

企业微信截图_d6ad669e-5ed0-4e6b-967f-f87135b71fb9.png

使用json格式检查工具的另外一个好处是可以将文本内容格式化,查看起来更方便

企业微信截图_ff99b704-9ae1-468f-8fdc-31a38b936975.png
// 读取本地JSON文件
- (NSArray *)readLocalFileWithName:(NSDictionary *)name {
    // 获取文件路径;注意,如果在framework中,这里就不一定是mainBundle了
    NSString *path = [[NSBundle mainBundle] pathForResource:name ofType:@"json"];
    // 将文件数据化
    NSData *data = [[NSData alloc] initWithContentsOfFile:path];
    // 对数据进行JSON格式化并返回字典形式
    return [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil];
}

数据Model化

企业微信截图_b0dbeb1b-9764-46eb-97cb-5375ecb33014.png
@interface ZXSDistrictModel : NSObject

// 名称
@property (copy, nonatomic) NSString *name;

// 编码
@property (copy, nonatomic) NSString *code;

@end
@interface ZXSCityModel : NSObject

// 名称
@property (copy, nonatomic) NSString *name;

// 编码
@property (copy, nonatomic) NSString *code;

// 所属的区
@property (copy, nonatomic) NSArray<ZXSDistrictModel *> *districtArray;

@end
@interface ZXSProvinceModel : NSObject

// 名称
@property (copy, nonatomic) NSString *name;

// 编码
@property (copy, nonatomic) NSString *code;

// 所属的市
@property (copy, nonatomic) NSArray<ZXSCityModel *> *cityArray;

@end
企业微信截图_212c5123-ec46-48e8-b3aa-8c99f4026048.png

界面

企业微信截图_078e9b94-512a-4372-9b4e-ad832d2fa27a.png
@interface ZXSAreaCellModel : NSObject

// 省市区的名称
@property (copy, nonatomic) NSString *name;

// 省市区的编码
@property (copy, nonatomic, nullable) NSString *code;

// 是否选中
@property (assign, nonatomic) BOOL isSelect;

@end
// 通过省对象创建实例
+ (instancetype)instanceWithProvinceModel:(ZXSProvinceModel *)province {
    ZXSAreaCellModel *cellModel = [[ZXSAreaCellModel alloc] init];
    cellModel.name = province.name;
    cellModel.code = province.code;
    cellModel.isSelect = NO;
    return cellModel;
}

// 通过市对象创建实例
+ (instancetype)instanceWithCityModel:(ZXSCityModel *)city {
    ZXSAreaCellModel *cellModel = [[ZXSAreaCellModel alloc] init];
    cellModel.name = city.name;
    cellModel.code = city.code;
    cellModel.isSelect = NO;
    return cellModel;
}

// 通过区对象创建实例
+ (instancetype)instanceWithDistrictModel:(ZXSDistrictModel *)district {
    ZXSAreaCellModel *cellModel = [[ZXSAreaCellModel alloc] init];
    cellModel.name = district.name;
    cellModel.code = district.code;
    cellModel.isSelect = NO;
    return cellModel;
}
@interface ZXSAreaCell : UITableViewCell

// 更新cell
- (void)updateWithCellModel:(ZXSAreaCellModel *)cellModel;

@end

只有两个对象,表示名称的标签,以及选中标志图片

@interface ZXSAreaCell ()

// 选项标签
@property (weak, nonatomic) IBOutlet UILabel *itemLabel;

// 选中标志
@property (weak, nonatomic) IBOutlet UIImageView *selectImage;

@end
// 更新cell
- (void)updateWithCellModel:(ZXSAreaCellModel *)cellModel {
    if (cellModel) {
        self.itemLabel.text = cellModel.name;
        self.selectImage.hidden = !cellModel.isSelect;
    }
}

调用接口

@interface ZXSAreaModel : NSObject

// 省名称
@property (copy, nonatomic) NSString *provinceName;

// 省编码
@property (copy, nonatomic) NSString *provinceCode;

// 市名称
@property (copy, nonatomic) NSString *cityName;

// 市编码
@property (copy, nonatomic) NSString *cityCode;

// 区名称
@property (copy, nonatomic) NSString *districtName;

// 区编码
@property (copy, nonatomic) NSString *districtCode;

@end
@interface ZXSAreaSelector : NSObject

// present方式显示地区选择
+ (void)launchOnContorller:(UIViewController *)vc currentArea:(nullable ZXSAreaModel *)currentArea select:(nullable void(^)(ZXSAreaModel *selectArea))selectBlock
                    cancel:(nullable void(^)(void))cancelBlock;

@end

控制器的属性

数据接口所需要信息都是通过控制的外部属性提供的。

@interface ZXSAreaSelectorViewController : UIViewController

// 当前选中地区;
@property (strong, nonatomic, nullable) ZXSAreaModel *currentArea;

// 选择后的block
@property (copy, nonatomic, nullable) void(^selectBlock)(ZXSAreaModel *selectArea);

// 取消的block
@property (copy, nonatomic, nullable) void(^cancelBlock)(void);

// 所有的省数据
@property (strong, nonatomic, nonnull) NSArray<ZXSProvinceModel *> *provinceArray;

@end

属性观察

// 根据索引设置下划线位置和标签颜色
- (void)setAreaIndex:(ZXSAreaIndex)areaIndex {
    _areaIndex = areaIndex;
    
    // 下划线位置
    self.maskLeftConstant.constant = areaIndex * kIndexStep;
    
    // 标签颜色
    switch (areaIndex) {
        case ZXSAreaIndexProvince:
            self.provinceLabel.textColor = kBlueColor;
            self.cityLabel.textColor = kBlackColor087;
            self.districtLabel.textColor = kBlackColor087;
            break;
        case ZXSAreaIndexCity:
            self.provinceLabel.textColor = kBlackColor087;
            self.cityLabel.textColor = kBlueColor;
            self.districtLabel.textColor = kBlackColor087;
            break;
        case ZXSAreaIndexDistrict:
            self.provinceLabel.textColor = kBlackColor087;
            self.cityLabel.textColor = kBlackColor087;
            self.districtLabel.textColor = kBlueColor;
            break;
        default:
            break;
    }
    
    // 表格数据源设置
    switch (areaIndex) {
        case ZXSAreaIndexProvince:
            self.dataSource = self.provinceDataSource;
            break;
        case ZXSAreaIndexCity:
            self.dataSource = self.cityDataSource;
            break;
        case ZXSAreaIndexDistrict:
            self.dataSource = self.districtDataSource;
            break;
        default:
            break;
    }
}

使用方式

用起来就相对比较简单:

@interface ZXSViewController ()

@property (strong, nonatomic) ZXSAreaModel *area;

@end

- (IBAction)areaSelectorButtonTouched:(id)sender {
    [ZXSTool launchAreaSelectorOnContorller:self currentArea:self.area select:^(ZXSAreaModel * _Nonnull selectArea) {
        self.area = selectArea;
        NSLog(@"%@%@%@", selectArea.provinceName, selectArea.cityName, selectArea.districtName);
        NSLog(@"%@%@%@", selectArea.provinceCode, selectArea.cityCode, selectArea.districtCode);
    } cancel:nil];
}

Demo地址

这个组件已经上传GitHub,支持CocoaPod

ZXSTool

上一篇下一篇

猜你喜欢

热点阅读