//
|
// MOFSAddressPickerView.m
|
// MOFSPickerManager
|
//
|
// Created by luoyuan on 16/8/31.
|
// Copyright © 2016年 luoyuan. All rights reserved.
|
//
|
|
#import "MOFSAddressPickerView.h"
|
|
#define UISCREEN_WIDTH [UIScreen mainScreen].bounds.size.width
|
#define UISCREEN_HEIGHT [UIScreen mainScreen].bounds.size.height
|
|
@interface MOFSAddressPickerView() <UIPickerViewDelegate, UIPickerViewDataSource, NSXMLParserDelegate>
|
|
@property (nonatomic, strong) NSXMLParser *parser;
|
|
@property (nonatomic, strong) UIView *bgView;
|
@property (nonatomic, strong) NSMutableArray<AddressModel *> *dataArr;
|
|
@property (nonatomic, assign) NSInteger selectedIndex_province;
|
@property (nonatomic, assign) NSInteger selectedIndex_city;
|
@property (nonatomic, assign) NSInteger selectedIndex_area;
|
|
@property (nonatomic, assign) BOOL isGettingData;
|
@property (nonatomic, strong) void (^getDataCompleteBlock)(void);
|
|
@property (nonatomic, strong) dispatch_semaphore_t semaphore;
|
@property (nonatomic, assign) BOOL isSection; //0 < numberOfSection <= 3
|
|
@end
|
|
@implementation MOFSAddressPickerView
|
|
#pragma mark - setter
|
|
- (void)setNumberOfSection:(NSInteger)numberOfSection {
|
if (numberOfSection <= 0 || numberOfSection > 3) {
|
_numberOfSection = 3;
|
} else {
|
_numberOfSection = numberOfSection;
|
}
|
dispatch_async(dispatch_get_main_queue(), ^{
|
[self reloadAllComponents];
|
});
|
}
|
|
#pragma mark - create UI
|
|
- (instancetype)initWithFrame:(CGRect)frame {
|
|
self.semaphore = dispatch_semaphore_create(1);
|
|
[self initToolBar];
|
[self initContainerView];
|
|
CGRect initialFrame;
|
if (CGRectIsEmpty(frame)) {
|
initialFrame = CGRectMake(0, self.toolBar.frame.size.height, UISCREEN_WIDTH, 216);
|
} else {
|
initialFrame = frame;
|
}
|
self = [super initWithFrame:initialFrame];
|
if (self) {
|
self.backgroundColor = [UIColor whiteColor];
|
|
self.delegate = self;
|
self.dataSource = self;
|
|
[self initBgView];
|
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
|
|
[self getData];
|
dispatch_queue_t queue = dispatch_queue_create("my.current.queue", DISPATCH_QUEUE_CONCURRENT);
|
dispatch_barrier_async(queue, ^{
|
dispatch_async(dispatch_get_main_queue(), ^{
|
[self reloadAllComponents];
|
});
|
});
|
});
|
}
|
return self;
|
}
|
|
- (void)selectRow:(NSInteger)row inComponent:(NSInteger)component animated:(BOOL)animated {
|
if (component >= self.numberOfComponents) {
|
return;
|
}
|
[super selectRow:row inComponent:component animated:animated];
|
switch (component) {
|
case 0:
|
self.selectedIndex_province = row;
|
self.selectedIndex_city = 0;
|
self.selectedIndex_area = 0;
|
if (self.numberOfSection > 1) {
|
[self reloadComponent:1];
|
}
|
if (self.numberOfSection > 2) {
|
[self reloadComponent:2];
|
}
|
break;
|
case 1:
|
self.selectedIndex_city = row;
|
self.selectedIndex_area = 0;
|
if (self.numberOfSection > 2) {
|
[self reloadComponent:2];
|
}
|
break;
|
case 2:
|
self.selectedIndex_area = row;
|
break;
|
default:
|
break;
|
}
|
}
|
|
- (void)initToolBar {
|
self.toolBar = [[MOFSToolView alloc] initWithFrame:CGRectMake(0, 0, UISCREEN_WIDTH, 44)];
|
self.toolBar.backgroundColor = [UIColor whiteColor];
|
}
|
|
- (void)initContainerView {
|
self.containerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, UISCREEN_WIDTH, UISCREEN_HEIGHT)];
|
self.containerView.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.4];
|
self.containerView.userInteractionEnabled = YES;
|
[self.containerView addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(hiddenWithAnimation)]];
|
}
|
|
- (void)initBgView {
|
self.bgView = [[UIView alloc] initWithFrame:CGRectMake(0, UISCREEN_HEIGHT - self.frame.size.height - 44, UISCREEN_WIDTH, self.frame.size.height + self.toolBar.frame.size.height)];
|
}
|
|
#pragma mark - Action
|
|
- (void)showMOFSAddressPickerCommitBlock:(void(^)(NSString *address, NSString *zipcode))commitBlock cancelBlock:(void(^)(void))cancelBlock {
|
if (self.numberOfSection <= 0 || self.numberOfComponents > 3) {
|
self.numberOfSection = 3;
|
}
|
[self showWithAnimation];
|
|
__weak typeof(self) weakSelf = self;
|
self.toolBar.cancelBlock = ^ {
|
if (cancelBlock) {
|
[weakSelf hiddenWithAnimation];
|
cancelBlock();
|
}
|
};
|
|
self.toolBar.commitBlock = ^ {
|
if (commitBlock) {
|
[weakSelf hiddenWithAnimation];
|
if (weakSelf.dataArr.count > 0) {
|
AddressModel *addressModel = weakSelf.dataArr[weakSelf.selectedIndex_province];
|
CityModel *cityModel;
|
DistrictModel *districtModel;
|
if (addressModel.list.count > 0) {
|
cityModel = addressModel.list[weakSelf.selectedIndex_city];
|
}
|
if (cityModel && cityModel.list.count > 0) {
|
districtModel = cityModel.list[weakSelf.selectedIndex_area];
|
}
|
|
NSString *address;
|
NSString *zipcode;
|
if (!cityModel || weakSelf.numberOfComponents == 1) {
|
address = [NSString stringWithFormat:@"%@",addressModel.name];
|
zipcode = [NSString stringWithFormat:@"%@",addressModel.zipcode];
|
} else {
|
if (!districtModel || weakSelf.numberOfComponents == 2) {
|
address = [NSString stringWithFormat:@"%@-%@",addressModel.name,cityModel.name];
|
zipcode = [NSString stringWithFormat:@"%@-%@",addressModel.zipcode,cityModel.zipcode];
|
} else {
|
address = [NSString stringWithFormat:@"%@-%@-%@",addressModel.name,cityModel.name,districtModel.name];
|
zipcode = [NSString stringWithFormat:@"%@-%@-%@",addressModel.zipcode,cityModel.zipcode,districtModel.zipcode];
|
}
|
}
|
|
|
commitBlock(address, zipcode);
|
}
|
}
|
};
|
}
|
|
- (void)showWithAnimation {
|
[self addViews];
|
self.containerView.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.0];
|
CGFloat height = self.bgView.frame.size.height;
|
self.bgView.center = CGPointMake(UISCREEN_WIDTH / 2, UISCREEN_HEIGHT + height / 2);
|
[UIView animateWithDuration:0.25 animations:^{
|
self.bgView.center = CGPointMake(UISCREEN_WIDTH / 2, UISCREEN_HEIGHT - height / 2);
|
self.containerView.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.4];
|
}];
|
|
}
|
|
- (void)hiddenWithAnimation {
|
CGFloat height = self.bgView.frame.size.height;
|
[UIView animateWithDuration:0.25 animations:^{
|
self.bgView.center = CGPointMake(UISCREEN_WIDTH / 2, UISCREEN_HEIGHT + height / 2);
|
self.containerView.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.0];
|
} completion:^(BOOL finished) {
|
[self hiddenViews];
|
}];
|
}
|
|
- (void)addViews {
|
UIWindow *window = [UIApplication sharedApplication].keyWindow;
|
[window addSubview:self.containerView];
|
[window addSubview:self.bgView];
|
[self.bgView addSubview:self.toolBar];
|
[self.bgView addSubview:self];
|
}
|
|
- (void)hiddenViews {
|
[self removeFromSuperview];
|
[self.toolBar removeFromSuperview];
|
[self.bgView removeFromSuperview];
|
[self.containerView removeFromSuperview];
|
}
|
|
#pragma mark - get data
|
|
- (void)getData {
|
self.isGettingData = YES;
|
NSString *path = [[NSBundle mainBundle] pathForResource:@"province_data" ofType:@"xml"];
|
if (path == nil) {
|
for (NSBundle *bundle in [NSBundle allFrameworks]) {
|
path = [bundle pathForResource:@"province_data" ofType:@"xml"];
|
if (path != nil) {
|
break;
|
}
|
}
|
}
|
|
if (path == nil) {
|
self.isGettingData = NO;
|
if (self.getDataCompleteBlock) {
|
self.getDataCompleteBlock();
|
}
|
return;
|
}
|
|
if (!_dataArr) {
|
_dataArr = [NSMutableArray array];
|
}
|
if (_dataArr.count != 0) {
|
[_dataArr removeAllObjects];
|
}
|
|
self.parser = [[NSXMLParser alloc] initWithData:[NSData dataWithContentsOfFile:path]];
|
self.parser.delegate = self;
|
[self.parser parse];
|
|
}
|
|
|
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary<NSString *,NSString *> *)attributeDict {
|
if ([elementName isEqualToString:@"province"]) {
|
AddressModel *model = [[AddressModel alloc] initWithDictionary:attributeDict];
|
model.index = [NSString stringWithFormat:@"%lu", (unsigned long)self.dataArr.count];
|
[self.dataArr addObject:model];
|
} else if ([elementName isEqualToString:@"city"]) {
|
CityModel *model = [[CityModel alloc] initWithDictionary:attributeDict];
|
model.index = [NSString stringWithFormat:@"%lu", (unsigned long)self.dataArr.lastObject.list.count];
|
[self.dataArr.lastObject.list addObject:model];
|
} else if ([elementName isEqualToString:@"district"]) {
|
DistrictModel *model = [[DistrictModel alloc] initWithDictionary:attributeDict];
|
model.index = [NSString stringWithFormat:@"%lu", (unsigned long)self.dataArr.lastObject.list.lastObject.list.count];
|
[self.dataArr.lastObject.list.lastObject.list addObject: model];
|
}
|
}
|
|
- (void)parserDidEndDocument:(NSXMLParser *)parser {
|
self.isGettingData = NO;
|
if (self.getDataCompleteBlock) {
|
self.getDataCompleteBlock();
|
}
|
}
|
|
#pragma mark - search
|
|
- (void)searchType:(SearchType)searchType key:(NSString *)key block:(void(^)(NSString *result))block {
|
|
dispatch_semaphore_wait(self.semaphore, DISPATCH_TIME_FOREVER);
|
|
NSString *valueName = @"";
|
NSString *type = @"";
|
|
if (searchType == SearchTypeAddressIndex) {
|
valueName = @"index";
|
type = @"name";
|
} else if (searchType == SearchTypeZipcodeIndex) {
|
valueName = @"index";
|
type = @"zipcode";
|
} else {
|
valueName = searchType == SearchTypeAddress ? @"name" : @"zipcode";
|
type = searchType == SearchTypeAddress ? @"zipcode" : @"name";
|
}
|
|
if (self.isGettingData || !self.dataArr || self.dataArr.count == 0) {
|
__weak typeof(self) weakSelf = self;
|
self.getDataCompleteBlock = ^{
|
if (block) {
|
|
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
|
block([weakSelf searchByKey:key valueName:valueName type:type]);
|
});
|
|
dispatch_semaphore_signal(weakSelf.semaphore);
|
}
|
};
|
} else {
|
if (block) {
|
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
|
block([self searchByKey:key valueName:valueName type:type]);
|
});
|
dispatch_semaphore_signal(self.semaphore);
|
}
|
}
|
|
}
|
|
|
- (NSString *)searchByKey:(NSString *)key valueName:(NSString *)valueName type:(NSString *)type {
|
|
if ([key isEqualToString:@""] || !key) {
|
return @"";
|
}
|
|
NSArray *arr = [key componentsSeparatedByString:@"-"];
|
if (arr.count > 3) {
|
return @"error0"; //最多只能输入省市区三个部分
|
}
|
AddressModel *addressModel = (AddressModel *)[self searchModelInArr:_dataArr key:arr[0] type:type];
|
if (addressModel) {
|
if (arr.count == 1) { //只输入了省份
|
return [addressModel valueForKey:valueName];
|
}
|
CityModel *cityModel = (CityModel *)[self searchModelInArr:addressModel.list key:arr[1] type:type];
|
if (cityModel) {
|
if (arr.count == 2) { //只输入了省份+城市
|
return [NSString stringWithFormat:@"%@-%@",[addressModel valueForKey:valueName],[cityModel valueForKey:valueName]];
|
}
|
DistrictModel *districtModel = (DistrictModel *)[self searchModelInArr:cityModel.list key:arr[2] type:type];
|
if (districtModel) {
|
return [NSString stringWithFormat:@"%@-%@-%@",[addressModel valueForKey:valueName],[cityModel valueForKey:valueName],[districtModel valueForKey:valueName]];
|
} else {
|
return @"error3"; //输入区错误
|
}
|
} else {
|
return @"error2"; //输入城市错误
|
}
|
} else {
|
return @"error1"; //输入省份错误
|
}
|
|
|
}
|
|
- (NSObject *)searchModelInArr:(NSArray *)arr key:(NSString *)key type:(NSString *)type {
|
|
NSObject *object;
|
|
for (NSObject *obj in arr) {
|
if ([key isEqualToString:[obj valueForKey:type]]) {
|
object = obj;
|
break;
|
}
|
}
|
|
return object;
|
}
|
|
|
#pragma mark - UIPickerViewDelegate,UIPickerViewDataSource
|
|
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView {
|
return self.numberOfSection;
|
}
|
|
- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component {
|
AddressModel *addressModel;
|
if (self.dataArr.count > 0) {
|
addressModel = self.dataArr[self.selectedIndex_province];
|
}
|
|
CityModel *cityModel;
|
if (addressModel && addressModel.list.count > 0) {
|
cityModel = addressModel.list[self.selectedIndex_city];
|
}
|
if (self.dataArr.count != 0) {
|
if (component == 0) {
|
return self.dataArr.count;
|
} else if (component == 1) {
|
return addressModel == nil ? 0 : addressModel.list.count;
|
} else if (component == 2) {
|
return cityModel == nil ? 0 : cityModel.list.count;
|
} else {
|
return 0;
|
}
|
} else {
|
return 0;
|
}
|
|
}
|
|
- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component {
|
|
if (component == 0) {
|
AddressModel *addressModel = self.dataArr[row];
|
return addressModel.name;
|
} else if (component == 1) {
|
AddressModel *addressModel = self.dataArr[self.selectedIndex_province];
|
CityModel *cityModel = addressModel.list[row];
|
return cityModel.name;
|
} else if (component == 2) {
|
AddressModel *addressModel = self.dataArr[self.selectedIndex_province];
|
CityModel *cityModel = addressModel.list[self.selectedIndex_city];
|
DistrictModel *districtModel = cityModel.list[row];
|
return districtModel.name;
|
} else {
|
return nil;
|
}
|
}
|
|
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component {
|
switch (component) {
|
case 0:
|
self.selectedIndex_province = row;
|
self.selectedIndex_city = 0;
|
self.selectedIndex_area = 0;
|
if (self.numberOfSection > 1) {
|
[pickerView reloadComponent:1];
|
[pickerView selectRow:0 inComponent:1 animated:NO];
|
}
|
if (self.numberOfSection > 2) {
|
[pickerView reloadComponent:2];
|
[pickerView selectRow:0 inComponent:2 animated:NO];
|
}
|
break;
|
case 1:
|
self.selectedIndex_city = row;
|
self.selectedIndex_area = 0;
|
if (self.numberOfSection > 2) {
|
[pickerView reloadComponent:2];
|
[pickerView selectRow:0 inComponent:2 animated:NO];
|
}
|
break;
|
case 2:
|
self.selectedIndex_area = row;
|
break;
|
default:
|
break;
|
}
|
}
|
|
- (void)dealloc {
|
|
}
|
|
@end
|