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 。這點要特別注意。


效果展示

隨機點菜系統

結構

這裏寫圖片描述
這裏寫圖片描述

代碼

//  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

效果展示

這裏寫圖片描述

發佈了41 篇原創文章 · 獲贊 0 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章