@property(nonatomic,assign) id<UIPickerViewDataSource> dataSource;
@property(nonatomic,assign) id<UIPickerViewDelegate> delegate;
@property(nonatomic) BOOL showsSelectionIndicator;
@property(nonatomic,readonly) NSInteger numberOfComponents;
- (void)reloadAllComponents;
- (void)reloadComponent:(NSInteger)component;
- (NSInteger)selectedRowInComponent:(NSInteger)component;
- (void)selectRow:(NSInteger)row inComponent:(NSInteger)component animated:(BOOL)animated;
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView;
- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component;
- (CGFloat)pickerView:(UIPickerView *)pickerView widthForComponent:(NSInteger)component;
- (CGFloat)pickerView:(UIPickerView *)pickerView rowHeightForComponent:(NSInteger)component;
- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component;
- (UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(UIView *)view;
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component;
方法 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 。这点要特别注意。
// 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
// 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
// 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