首页 > 代码库 > iOS核心笔记——UIPickerView

iOS核心笔记——UIPickerView

1、UIPickerView简介

  • UIPickerView继承自UIView,且遵守了协议;UIPickerView的高度(height = 162)不能改变, 但UIPickerView中的行高可以改变。 

  • UIPickerView两个必须实现的数据源方法: 

  • UIPickerView常见属性:

     

  • UIPickerView代理方法:

#pragma mark - <UIPickerViewDelegate>
/**
 *  pickerView每一列宽度
 */
- (CGFloat)pickerView:(UIPickerView *)pickerView widthForComponent:(NSInteger)component{
    return 100;
}

/**
 *  pickerView每一行高度
 */
- (CGFloat)pickerView:(UIPickerView *)pickerView rowHeightForComponent:(NSInteger)component{
    return 60;
}

/**
 *  pickerView每行显示内容
 */
- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component{
    return @"贺华峰";
}

/**
 *  pickerView显示字符串时,字符串富文本属性(可设置字符串字体大小、字体颜色...),返回nil时不影响显示文字
 */
- (NSAttributedString *)pickerView:(UIPickerView *)pickerView attributedTitleForRow:(NSInteger)row forComponent:(NSInteger)component{
    return nil;
}

/**
 *  pickerView每行显示视图, 当与pickerView:titleForRow:forComponent:同时实现时, 优先调用
 */
- (UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(nullable UIView *)view{
    return nil;
}

/**
 *  pickerView选中某行或某列时调用, 只有用户拖拽才会调用
 */
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component {
    NSLog(@"%s", __func__);
}
  • UIPickerView显示?问题: 

    • 原因: 只设置了数据源, 没有设置代理实现返回pickerView要显示的内容; 所以, pickerView显示默认的?
  • 点击随机点餐按钮实现随机点餐:

    /**
    *  随机点餐
    */
    - (IBAction)random {
        for (int i = 0; i < self.foods.count; i++) {
            // 1. 随机数
            int random = arc4random_uniform((u_int32_t)[self.foods[i] count]);
            // 2. 选中pickerView对应的列、行
            [self.pickView selectRow:random inComponent:i animated:YES];
    
            // 3. 将随机选中的数据设置到对应的Label上, 此处的row切记不能再重新使用随机数
            //[self pickerView:self.pickView didSelectRow:arc4random_uniform((u_int32_t)[self.foods[i] count]) inComponent:i];
            [self pickerView:self.pickView didSelectRow:random inComponent:i];
        }
    }
    
    • 在实现随机点餐的时候两大注意事项:
      • 使用随机数函数时要注意每调用一次都会生成新的随机数, 如果要多次使用同一个随机数; 需要定义一个变量保存要多次使用的随机数。
      • 调用pickerView的selectRow:inComponent:animated:时, pickerView的代理方法pickerView:didSelectRow:inComponent:方法不会调用, 需要我们手动调用; 但是, 当用户拖拽pickerView时代理方法pickerView:didSelectRow:inComponent:方法会自动调用。

2、UIPickerView实现国旗选择(MVC模式)

  • Model(模型): HFFlag
    • 继承自NSObject类,设置属性保存数据;
  • View(视图): HFFlagView
    • 使用xib封装国旗视图,在数据模型的set方法中设置控件数据;
  • Controller(控制器): Controller
    • 懒加载读取plist文件,获取数据;
    • 实现数据源方法;
    • 实现代理方法,返回UIPickerView自定义显示视图。

3、UIDatePicker简介

  • UIDatePicker继承自UIControl: 

  • 使用UIDatePicker的三大步骤:

    • <1> 创建UIDatePicker:
      // 1. 创建UIDatePicker: 具有默认尺寸
      UIDatePicker *datePicker = [[UIDatePicker alloc] init];
      
    • <2> 设置UIDatePicker显示模式:

      // 2. 设置UIDatePicker显示模式
      datePicker.datePickerMode = UIDatePickerModeDate;
      
      • UIDatePicker显示模式: 
    • <3> 设置UIDatePicker显示时区:

      // 3. 设置UIDatePicker时区
      datePicker.locale = [NSLocale localeWithLocaleIdentifier:@"zh"];
      //    datePicker.locale = [NSLocale currentLocale]; // 当系统语言为中文时与上面代码等价
      //    datePicker.locale = [NSLocale systemLocale];
      
  • UIDatePicker监听时间变化:

    • 因为UIDatePicker继承自UIControl, 所以采用addTarget:action:forControlEvents:方法监听UIDatePicker上时间变化, 监听事件为UIControlEventValueChanged:
      [datePicker addTarget:self action:@selector(dateChange:) forControlEvents:UIControlEventValueChanged];
      

4、UITextField代理方法

  • 要实现UITextField代理方法, 必须先遵守协议; 成为UITextField的代理。
  #pragma mark - <UITextFieldDelegate>
  /**
    *  @return YES : 文本框允许编辑
    *  @return  NO : 文本框不允许编辑
    */
  - (BOOL)textFieldShouldBeginEditing:(UITextField *)textField{
      return NO;
  }

  /**
    *  文本框成为第一响应者
    */
  - (void)textFieldDidBeginEditing:(UITextField *)textField{
      NSLog(@"%@", textField);
  }

  /**
    *  是否允许当前文本框结束编辑
    *
    *  @return YES : 文本框允许结束编辑, 且当前正在编辑的文本框辞去第一响应者身份
    *  @return  NO : 当前文本框不允许结束编辑直至结束
    */
  - (BOOL)textFieldShouldEndEditing:(UITextField *)textField{
      return NO;
  }

  /**
    *  文本框已经结束编辑
    */
  - (void)textFieldDidEndEditing:(UITextField *)textField{
      NSLog(@"%s", __func__);
  }

  /**
    *  文本款是否能够显示输入
    *
    *  @param range     当前文本框光标所在位置, 与输入之后光标所在位置
    *  @param string    替换文本框中range范围内容
    *
    *  @return YES : 输入文本框的内容能替换range范围,光标移动
    *  @return  NO : 文本框不能替换,光标不移动
    */
  - (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string{
      return NO;
  }

  /**
    *  只要点击文本框清除按钮, 调用此方法
    *
    *  @return YES : 点击清空按钮清空文本框
    *  @return  NO : 点击清空按钮忽略, 文本框内容不清空
    */
  - (BOOL)textFieldShouldClear:(UITextField *)textField{

      return YES;
  }

  /**
    *  只要点击键盘return键调用此方法
    */
  - (BOOL)textFieldShouldReturn:(UITextField *)textField{

      return NO;
  }
  • 以下属性是设置文本框下一次编辑开始时自动清空文本框内容,下一次编辑开始时会自动调用textFieldShouldClear:方法以清空文本框: 

  • 自定义键盘, 设置文本框的inputVeiw属性;自定义文本框输入视图。

5、将时间以格式字符串形式显示步骤:

  • <1> 获取要显示的时间;
  • <2> 创建时间格式管理对象;
  • <3> 设置时间格式对象的时间格式字符串;
  • <4> 时间格式对象调用其stringFromDate:方法, 传入要显示的时间; 返回格式时间字符串。

  • 示例程序:

    // 1. 创建datePicker
    UIDatePicker *datePicker = [[UIDatePicker alloc] init];
    datePicker.datePickerMode = UIDatePickerModeDate;
    datePicker.locale = [[NSLocale alloc] initWithLocaleIdentifier:@"zh"];
    
    // 2. 获取datePicker时间
    NSDate *date = datePicker.date;
    // 3. 时间格式管理对象
    NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
    // 4. 设置时间格式字符串
    formatter.dateFormat = @"yyyy-MM-dd";
    // 5. 获取格式时间字符串
    NSString *dateStr = [formatter stringFromDate:date];
    

细小知识点:

  • <1> storyboard中直接拖线设置控制器为控件的代理与数据源, 在控制器可以不用写明相应的协议; 因为连线时已经自动设置控制器遵守相应的协议, 为保持代码可读性通常依旧会在控制器代码中声明遵守相应的协议。

  • <2> Xcode中能直接使用jpg、png、gif格式的图片。

  • <3> id与instancetype区别:

    • instancetype: 作为方法的返回值类型时能自动识别当前接收类型与方法实质返回类型是否一致,不能声明变量;
    • id: 作为方法返回值类型时方法返回对象的接收类型可以是任意类型,且可以声明变量;id类型的对象可以调用任何方法,编译时不会报错;运行时如果调用了没有实现的方法程序会崩溃;id类型变量不能使用点语法。
  • <4> 字符串调用NSString类的capitalizedString方法,返回字符串首字母大写之后的字符串。

  • <5> 所有继承自UIControl类的控件都可以采用addTarget:action:forControlEvents:方法监听控件。

实用小技巧:

  • <1> NSLog方法使用%s重打印 __func__: 输出调用当前方法所在的类; 

  • <2> Debug中调试显示当前界面所有layer(图层): 

  • <3> Xcode快捷键:

    • 1、 command + option + 回车 : 分屏;
    • 2、 command + 回车 : 退出分屏。
    • 3、command + option + [ : 代码上调
    • 4、command + option + ] : 代码下调
    • 5、command + [ : 代码左移
    • 6、command + ] : 代码右移
  • <4> 当无法确认控件监听触发事件类型时, 可以将storyboard中控件连线到代码中以方便查看事件类型。 

 

iOS核心笔记——UIPickerView