UIPickerView【随机点菜系统 && 省市联动 && 选择国旗】

UIPickerView

1. UIPickerView的常见属性

  • 数据源(用来告诉UIPickerView有多少列多少行)
@property(nonatomic,assign) id<UIPickerViewDataSource> dataSource;
  • 代理(用来告诉UIPickerView每1列的每1行显示什么内容,监听UIPickerView的选择)
@property(nonatomic,assign) id<UIPickerViewDelegate>   delegate;
  • 是否要显示选中的指示器
@property(nonatomic)        BOOL                       showsSelectionIndicator;
  • 一共有多少列
@property(nonatomic,readonly) NSInteger numberOfComponents;

2. UIPickerView的常见方法

  • 重新刷新所有列
- (void)reloadAllComponents;
  • 重新刷新第component列
- (void)reloadComponent:(NSInteger)component;
  • 获得第component列的当前选中的行号
- (NSInteger)selectedRowInComponent:(NSInteger)component;
  • 自动选中第component列的第row行
- (void)selectRow:(NSInteger)row inComponent:(NSInteger)component animated:(BOOL)animated;

3. 数据源方法(UIPickerViewDataSource)

  • 一共有多少列
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView;
  • 第component列一共有多少行
- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component;

4. 代理方法(UIPickerViewDelegate)

  • 第component列的宽度是多少
- (CGFloat)pickerView:(UIPickerView *)pickerView widthForComponent:(NSInteger)component;
  • 第component列的行高是多少
- (CGFloat)pickerView:(UIPickerView *)pickerView rowHeightForComponent:(NSInteger)component;
  • 第component列第row行显示什么文字
- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component;
  • 第component列第row行显示怎样的view(内容)
- (UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(UIView *)view;
  • 选中了pickerView的第component列第row行
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component;

5. 注意

方法 1.- (void) selectRow:(NSInteger)row inComponent:(NSInteger)component animated:(BOOL)animated;
方法 2.-(void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component;

注意:这两个方法非常容易弄混,这里重点说一下
1. 方法 1 是UIPickerView自身的方法; 方法 2 是UIPickerView代理的方法
2. 方法 2 是选中了pickerView的第component列第row行,只有人选中了PickerView,才会自动调用,但我们可以在程序中实现主动加载,即人不选中PickerView,我们可以用代码主动加载。
3. 方法 1 是自动选中第component列的第row行,UIPickerView会自动跳转到component列row行。跳转以后不会自动执行方法 2 。这点要特别注意。

效果展示

随机点菜系统

结构

UIPickerView【随机点菜系统 && 省市联动 && 选择国旗】_第1张图片
UIPickerView【随机点菜系统 && 省市联动 && 选择国旗】_第2张图片

代码

// ViewController.m

#import "ViewController.h"

@interface ViewController () <UIPickerViewDataSource, UIPickerViewDelegate>
@property (strong, nonatomic) NSArray *food;
@property (weak, nonatomic) IBOutlet UILabel *fruitLabel;
@property (weak, nonatomic) IBOutlet UILabel *mainLabel;
@property (weak, nonatomic) IBOutlet UILabel *drinkLabel;
@property (weak, nonatomic) IBOutlet UIPickerView *pickerView;
- (IBAction)randomMenu;
@end

@implementation ViewController
- (NSArray *)food{
    if(_food == nil){
        NSString *path = [[NSBundle mainBundle] pathForResource:@"foods.plist" ofType:nil];
        _food = [NSArray arrayWithContentsOfFile:path];
    }
    return _food;
}
- (void)viewDidLoad {
    [super viewDidLoad];
// self.fruitLabel.text = self.food[0][0];
// self.mainLabel.text = self.food[1][0];
// self.drinkLabel.text = self.food[2][0];
    // 初始化
    // 默认选中数据,第一行数据
    for (int i = 0; i < self.food.count; ++i) {
        [self pickerView:nil didSelectRow:0 inComponent:i];
    }
}

- (BOOL)prefersStatusBarHidden{
    return YES;
}
/** * 一共有多少列 */
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView{
    return self.food.count;
}

/** * 第component列显示多少行 */
- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component{
    return [self.food[component] count];
}

/** * 第component列的第row行显示什么文字 */
- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component{
    return self.food[component][row];
}

/** * 选中了第component列的第row行(只有人选中了PickerView,才会自动调用,但我们可以在程序中实在主动加载,即人不选中PickerView,我们可以用代码主动加载) */
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component{
    if (component == 0) { // 水果
        self.fruitLabel.text = self.food[component][row];
    } else if (component == 1) { // 主菜
        self.mainLabel.text = self.food[component][row];
    } else if (component == 2) { // 饮料
        self.drinkLabel.text = self.food[component][row];
    }
}
/** * 随机选择菜单 */
- (IBAction)randomMenu{
    for (int i = 0; i < self.food.count; ++i) {
        // 获取每列有多少行
        NSInteger num = [self.food[i] count];
        // 在行范围产生随机数据,做为新的行号
        NSInteger randomRow = arc4random() % num;

        // 获取旧的行号
        NSInteger oldRow = [self.pickerView selectedRowInComponent:i];

        while (oldRow == randomRow) {
            randomRow = arc4random() % num;
        }
#warning 要自动改变PIckerview选中的行,要使用pickerview的一个方法
        // 更改UIPickerView选中的数据

        // 自动选中第component列的第row行,UIPickerView会自动跳转到component列,row行。
        [self.pickerView selectRow:randomRow inComponent:i animated:YES];

        // 更改label的数据(主动加载)
        [self pickerView:nil didSelectRow:randomRow inComponent:i];
    }
}
@end

效果展示

UIPickerView【随机点菜系统 && 省市联动 && 选择国旗】_第3张图片

省市联动

结构

UIPickerView【随机点菜系统 && 省市联动 && 选择国旗】_第4张图片
UIPickerView【随机点菜系统 && 省市联动 && 选择国旗】_第5张图片

代码

// ViewController.m
#import "ViewController.h"
#import "Province.h"

@interface ViewController () <UIPickerViewDataSource, UIPickerViewDelegate>
@property (strong, nonatomic) NSArray *provinces;
/** * 当前默认选中的省份 */
@property (nonatomic, assign) NSInteger indexOfProvince;

@end

@implementation ViewController



- (void)viewDidLoad {
    [super viewDidLoad];
}

- (BOOL)prefersStatusBarHidden{
    return YES;
}

/** * 数据懒加载 */

- (NSArray *)provinces{
    if(_provinces == nil){
        NSString *path = [[NSBundle mainBundle] pathForResource:@"provinces.plist" ofType:nil];
        NSArray *dictArray = [NSArray arrayWithContentsOfFile:path];
        NSMutableArray *provinceArray = [NSMutableArray array];
        for(NSDictionary *dict in dictArray) {
            Province *province = [Province provinceWithDict:dict];
            [provinceArray addObject:province];
        }
        _provinces = provinceArray;
    }
    return _provinces;
}

- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView{
    return 2;
}

- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component{
    if(component == 0)
        return self.provinces.count;
    Province *provice = self.provinces[self.indexOfProvince];
    return provice.cities.count;
}

- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component{
    if(component == 0){
        //对应列行的省份
        Province *provice = self.provinces[row];
        return provice.name;
    }
    //获取选中的城市,显示城市名字
    Province *selectedProvice = self.provinces[self.indexOfProvince];
    return selectedProvice.cities[row];
}

- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component{
    if(component == 0){
        self.indexOfProvince = row;
        //全部刷新
        //[pickerView reloadAllComponents];

        //部份刷新
        [pickerView reloadComponent:1];
         //不管之前第二列选中第几行,重新刷新数据后,都自动跳转到每二列的第一行
        [pickerView selectRow:0 inComponent:1 animated:YES];
    }
}
@end
// Province.h

#import <Foundation/Foundation.h>

@interface Province : NSObject
@property (copy, nonatomic) NSString *name;
@property (strong, nonatomic) NSArray *cities;


+ (instancetype)provinceWithDict:(NSDictionary *)dict;

- (instancetype)initWithDict:(NSDictionary *)dict;

@end
// Province.m
#import "Province.h"

@implementation Province

+ (instancetype)provinceWithDict:(NSDictionary *)dict{
    return [[self alloc] initWithDict:dict];
}

- (instancetype)initWithDict:(NSDictionary *)dict{
    if(self = [super init]){
        [self setValuesForKeysWithDictionary:dict];
    }
    return self;
}
@end

效果展示

UIPickerView【随机点菜系统 && 省市联动 && 选择国旗】_第6张图片

选择国旗

结构

UIPickerView【随机点菜系统 && 省市联动 && 选择国旗】_第7张图片 UIPickerView【随机点菜系统 && 省市联动 && 选择国旗】_第8张图片
UIPickerView【随机点菜系统 && 省市联动 && 选择国旗】_第9张图片 UIPickerView【随机点菜系统 && 省市联动 && 选择国旗】_第10张图片

代码

// ViewController.m

#import "ViewController.h"
#import "FlagView.h"
#import "Flag.h"

@interface ViewController () <UIPickerViewDataSource, UIPickerViewDelegate>
@property (strong, nonatomic) NSArray *flags;


@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
}

- (BOOL)prefersStatusBarHidden{
    return YES;
}

- (NSArray *)flags{
    if(_flags == nil){
        NSString *path = [[NSBundle mainBundle] pathForResource:@"flags.plist" ofType:nil];
        NSArray *dictArray = [NSArray arrayWithContentsOfFile:path];
        NSMutableArray *flagArray = [NSMutableArray array];
        for(NSDictionary *dict in dictArray){
            Flag *flag = [Flag flagWithDict:dict];
            [flagArray addObject:flag];
        }
        _flags = flagArray;
    }
    return _flags;
}

- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView{
    return 1;
}

- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component{
    return self.flags.count;
}
#pragma mark 自定义Pickerview的行

#warning UIPikcerView循环引用在ios7以后,不太明显,但是确实还是会循环引用,在ios6,view的循环引用是非常明显
- (UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(UIView *)view{

    //如果有重用的view,会传一个view进来
    FlagView *flagView = (FlagView *)view;
    if(flagView == nil){
        flagView = [FlagView flagView];
    }
    flagView.flag = self.flags[row];
    NSLog(@"-----view = %p, flagView = %p", view, flagView);
    return flagView;
}

- (CGFloat)pickerView:(UIPickerView *)pickerView rowHeightForComponent:(NSInteger)component{
    return [FlagView flagViewHeight];
}
@end
// FlagView.h

#import <UIKit/UIKit.h>
@class Flag;

@interface FlagView : UIView

+ (instancetype)flagView;
+ (CGFloat)flagViewHeight;
@property (strong, nonatomic) Flag *flag;
@end
// FlagView.m

#import "FlagView.h"
#import "Flag.h"

@interface FlagView()
@property (weak, nonatomic) IBOutlet UIImageView *iconView;
@property (weak, nonatomic) IBOutlet UILabel *nameView;

@end

@implementation FlagView

+ (instancetype)flagView{
   return  [[[NSBundle mainBundle] loadNibNamed:@"FlagView" owner:nil options:nil] lastObject];
}

- (void)setFlag:(Flag *)flag{
    _flag = flag;
    self.iconView.image = [UIImage imageNamed:flag.icon];
    self.nameView.text = flag.name;
}

+ (CGFloat)flagViewHeight{
    return 50;
}
@end
// flag.h

#import <Foundation/Foundation.h>

@interface Flag : NSObject
@property (copy, nonatomic) NSString *name;
@property (copy, nonatomic) NSString *icon;

+ (instancetype)flagWithDict:(NSDictionary *)dict;

- (instancetype)initWithDict:(NSDictionary *)dict;

@end
// flag.m

#import "Flag.h"

@implementation Flag

+ (instancetype)flagWithDict:(NSDictionary *)dict{
    return [[self alloc] initWithDict:dict];
}

- (instancetype)initWithDict:(NSDictionary *)dict{
    if(self = [super init]){
        [self setValuesForKeysWithDictionary:dict];
    }
    return self;
}

@end

效果展示

UIPickerView【随机点菜系统 && 省市联动 && 选择国旗】_第11张图片

你可能感兴趣的:(UIPickerView【随机点菜系统 && 省市联动 && 选择国旗】)