单军华
2018-07-19 83b9d5c682b21d88133f24da0f94dd56bd79e687
screendisplay/Pods/MOFSPickerManager/MOFSPickerManagerDemo/MOFSPickerManager/MOFSAddressPickerView.m
New file
@@ -0,0 +1,462 @@
//
//  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