2018-06-08 滚轮的学习

一.创建Tab Bar Controller和他们的子控制器

1.Tab Bar Controller

在Main.storyboard中选取Tab Bar Controller,并把它拖动进去,可以发现会有一个自带了两个View Controller的Tab Bar Controller出现了。



我们再新建三个View Controller,并从Tab Bar Controller里面右键到子控制器中,选择Relationship Segue中的view controllers:



连接完毕后,我们可以看到,一个Tab Bar Controller控制了五个子控制器。

2.子控制器的底栏

我们选取每一个View Controller的底栏,右方工具栏选择第四项,可以看到这里面有Title和Image,选取我们要的Title和Image就可以了。



这样,我们的Tab Bar Controller和子控制器都成功建立了。


二.实现日期选取器

首先在工具栏选取一个Date Picker和一个Button,并进行相应的布局操作,记得关联相应的方法。这里的Date Picker选择右键,在@interface和@property之间建立一个变量

@interface DatePickerViewController ()
@property (weak, nonatomic) IBOutlet UIDatePicker *datePicker;

@end

然后在初始化的时候把这个datePicker设立一个日期:

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    
    NSDate *now = [NSDate date];
    [self.datePicker setDate: now animated: NO];
}

在触发按钮方法的时候则要显示出这个日期(直接用.date获取这个实例):

- (IBAction)buttonPressed:(UIButton *)sender {
    NSDate *date = self.datePicker.date;
    NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init];
    [dateFormat setDateFormat: @"yyyy-MM-dd HH:mm"];
    NSString *theDate = [dateFormat stringFromDate: date];
    NSString *msg = [[NSString alloc] initWithFormat: @"The date is %@", theDate];
    UIAlertController *alert = [UIAlertController alertControllerWithTitle: @"Date is selected"
                                                                   message: msg
                                                            preferredStyle: UIAlertControllerStyleAlert];
    UIAlertAction *action = [UIAlertAction actionWithTitle: @"Yes!"
                                                     style: UIAlertActionStyleDefault
                                                   handler: nil];
    [alert addAction: action];
    [self presentViewController: alert
                       animated: YES
                     completion: nil];
}

三.实现单滚轮选取器

首先要在.h文件里面声明委托,表明该控制器将遵循这两个协议:

#import 

@interface SingleComponentViewController : UIViewController  

@end

在.m文件建立两个变量,一个关联到单滚轮选取器,一个是这个程序所用到的列表:

@interface SingleComponentViewController ()
@property (weak, nonatomic) IBOutlet UIPickerView *singlePicker;
@property (strong, nonatomic) NSArray *characterNames;
@end

先初始化这个列表:

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    self.characterNames = @[@"Hoben", @"jp", @"Eric", @"Road", @"WhoWhenHow",
                            @"GuanGuan", @"CJ", @"Shit"];
}

然后在选取按钮的时候获得索引并打印出来(用selectedRowInComponent):

- (IBAction)buttonPressed:(id)sender {
    //获得选取的第一个滚轮的索引
    NSInteger row = [self.singlePicker selectedRowInComponent: 0];
    //获得索引对应的row
    NSString *selected = self.characterNames[row];
    NSString *title = [[NSString alloc] initWithFormat: @"You select %@", selected];
    UIAlertController *alert = [UIAlertController alertControllerWithTitle: title
                                                                   message: @"Thank you for choosing"
                                                            preferredStyle: UIAlertControllerStyleAlert];
    UIAlertAction *action = [UIAlertAction actionWithTitle: @"You're welcome"
                                                     style: UIAlertActionStyleDefault
                                                   handler: nil];
    [alert addAction: action];
    [self presentViewController: alert
                       animated: YES
                     completion: nil];
}

最后实现协议需要实现的方法:

- (NSInteger)numberOfComponentsInPickerView:(nonnull UIPickerView *)pickerView {
    //选项可以包括多个滚轮,这里为1
    return 1;
}

- (NSInteger)pickerView:(nonnull UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component {
    //选项包含多少行数据,这里为count数量
    return [self.characterNames count];
}

- (NSString *) pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component {
    //指定滚轮中指定行的数据
    return self.characterNames[row];
}

最后要记得将委托关联到相应的文件里面:



四.实现双滚轮选取器

双/多滚轮选取器中,滚轮从左到右的component分别为0,1,2...所以我们选取滚轮选择的内容的时候,一定要注意component的类别。

#define kFillingComponent 0
#define kBreadComponent 1

其他的和单滚轮没什么不同了,无非就是多了一个NSArray而已

- (IBAction)buttonPressed:(id)sender {
    NSInteger fillingRow = [self.doublePicker selectedRowInComponent: kFillingComponent];
    NSInteger breadRow = [self.doublePicker selectedRowInComponent: kBreadComponent];
    
    NSString *filling = self.fillingTypes[fillingRow];
    NSString *bread = self.breadTypes[breadRow];
    
    NSString *msg = [[NSString alloc] initWithFormat: @"Your %@ on %@ bread is ready.",
                     filling, bread];
    
    UIAlertController *alert = [UIAlertController alertControllerWithTitle: @"Thank you for order"
                                                                   message: msg
                                                            preferredStyle: UIAlertControllerStyleAlert];
    UIAlertAction *action = [UIAlertAction actionWithTitle: @"Great!"
                                                     style: UIAlertActionStyleDefault
                                                   handler: nil];
    
    [alert addAction: action];
    [self presentViewController: alert
                       animated: YES
                     completion: nil];
}

把相应的委托方法改一改,注意component类别的讨论:

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

- (NSInteger)pickerView:(nonnull UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component {
    if (component == kBreadComponent)
        return [self.breadTypes count];
    else
        return [self.fillingTypes count];
}

- (NSString *) pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component {
    if (component == kBreadComponent)
        return self.breadTypes[row];
    else
        return self.fillingTypes[row];
}

五.实现字典选取器

在双滚轮的基础上,我们再弄个邮政编码系统出来,要求在不同州会显示不同区间的邮政编码,会有一个states数组和一个zips数组,分别存放着州的名字和邮政编号,利用教材给的stateZips数据,分成这两个数组并显示出来:

@interface DependentComponentViewController ()

@property (strong, nonatomic) NSDictionary *stateZips;
@property (strong, nonatomic) NSArray *states;
@property (strong, nonatomic) NSArray *zips;
@property (weak, nonatomic) IBOutlet UIPickerView *dependentPicker;

@end

我们要先在viewDidLoad里面初始化这些数据,先读取dictionary,再根据字典里面的key和value,获得相对应的州和邮政编码。

NSString *path = [bundle pathForResource: @"statedictionary" ofType: @"plist"];

self.stateZips = [NSDictionary dictionaryWithContentsOfFile: path];
//对列表按字母排序
NSArray *allStates = [self.stateZips allKeys];
NSArray *sortedStates = [allStates sortedArrayUsingSelector: @selector(compare:)];
self.states = sortedStates;

//获得对应的邮政编码数组
NSString *selectedState = self.states[0];
self.zips = self.stateZips[selectedState];

点击按钮触发的事件同样是不变的

- (IBAction)buttonPressed:(id)sender {
    NSInteger stateRow = [self.dependentPicker selectedRowInComponent: kStateComponent];
    NSInteger zipRow = [self.dependentPicker selectedRowInComponent: kZipComponent];
    NSString *state = self.states[stateRow];
    NSString *zip = self.zips[zipRow];
    
    NSString *title = [[NSString alloc] initWithFormat: @"You select zip code %@.", zip];
    NSString *msg = [[NSString alloc] initWithFormat: @"%@ is in %@.", zip, state];
    
    UIAlertController *alert = [UIAlertController alertControllerWithTitle: title
                                                                   message: msg
                                                            preferredStyle: UIAlertControllerStyleAlert];
    
    UIAlertAction *action = [UIAlertAction actionWithTitle: @"OK"
                                                     style: UIAlertActionStyleDefault
                                                   handler: nil];
    
    [alert addAction: action];
    [self presentViewController: alert
                       animated: YES
                     completion: nil];
}

协议前三个方法同样也是不变的:

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

- (NSInteger) pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component
{
    if (component == kStateComponent)
        return [self.states count];
    else
        return [self.stateZips count];
}
- (NSString *) pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component
{
    if (component == kStateComponent)
        return self.states[row];
    else
        return self.zips[row];
}

但是这里多了一个方法,是根据第一个滚轮而变化第二个滚轮的方法:

- (void) pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component
{
    //一旦左侧滚轮发生变化,则右侧也会发生变化
    if (component == kStateComponent) {
        NSString *selectedState = self.states[row];
        self.zips = self.stateZips[selectedState];
        //zips数组发生变化之后重新读取zips数组
        [self.dependentPicker reloadComponent: kZipComponent];
        //并将zips滚轮置零
        [self.dependentPicker selectRow: 0
                            inComponent: kZipComponent
                               animated: YES];
    }
}

六.遇到的坑

1.Tab Bar显示不出底部图片


是这个!不是上面那个栏!

2.plist加载不出来:

原来是我误会了,将plist加载到了Assets.xcassets里面去,path一直报错为nil,后面复制到DataPicker文件夹就可以了。

3.忘记选delegate:

记得这一步!不然是不会生效的!


4.Button点击无反应:

我按书上这样操作之后,发现根本没有用:



后来才发现,要直接在视图中选中Button,直接在ViewController.m里面实现就可以了,根本不用那么麻烦。

5.书上自带的调用date方法显示日期不正确

参考https://blog.csdn.net/mamong/article/details/8487599,把格式改了一下,才正确,好坑啊。。这官方api。

你可能感兴趣的:(2018-06-08 滚轮的学习)