iOS开发基础24-UIPickerView、UITextField、KVC、UIDatePicker、控制器及导航控制器
在iOS开发中,涉及的UI组件和类非常丰富。本文将详细介绍UIPickerView的使用、注册界面中UITextField的处理、自定义键盘的实现、控制器的创建和管理、以及导航控制器的使用。
一、UIPickerView的简单使用
1. UIPickerViewDataSource
要使用UIPickerView
,首先需要实现其数据源协议UIPickerViewDataSource
。以下两个方法必须实现:
// 返回有多少列
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView {
return 1; // 示例中返回1列
}
// 返回第component列有多少行
- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component {
return 10; // 示例中返回10行
}
2. UIPickerViewDelegate
UIPickerViewDelegate
包括了定义UIPickerView
外观和行为的方法。以下是一些常用的方法:
// 返回第component列的宽度
- (CGFloat)pickerView:(UIPickerView *)pickerView widthForComponent:(NSInteger)component {
return 100.0; // 示例中宽度为100.0
}
// 返回第component列的行高
- (CGFloat)pickerView:(UIPickerView *)pickerView rowHeightForComponent:(NSInteger)component {
return 40.0; // 示例中行高为40.0
}
// 返回第component列第row行的标题
- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component {
return [NSString stringWithFormat:@"Row %ld", (long)row];
}
// 返回第component列第row行的富文本标题
- (NSAttributedString *)pickerView:(UIPickerView *)pickerView attributedTitleForRow:(NSInteger)row forComponent:(NSInteger)component {
NSString *title = [NSString stringWithFormat:@"Row %ld", (long)row];
NSAttributedString *attributedTitle = [[NSAttributedString alloc] initWithString:title attributes:@{NSForegroundColorAttributeName:[UIColor redColor]}];
return attributedTitle;
}
// 返回第component列第row行的视图控件
- (UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(UIView *)view {
UILabel *label = (UILabel *)view;
if (!label) {
label = [[UILabel alloc] init];
}
label.text = [NSString stringWithFormat:@"Row %ld", (long)row];
label.textAlignment = NSTextAlignmentCenter;
return label;
}
// 当用户选中某一行时调用
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component {
NSLog(@"Selected Row: %ld", (long)row);
}
二、注册界面中的UITextField处理
1. UITextFieldDelegate
在注册界面中,有时需要拦截用户输入,通过实现以下UITextFieldDelegate
方法来控制文本框行为。
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
return NO; // 禁止用户手动输入,文本框内容只能选择
}
另外两个常用方法:
// 是否允许开始编辑
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField {
return YES;
}
// 是否允许结束编辑
- (BOOL)textFieldShouldEndEditing:(UITextField *)textField {
return YES;
}
2. 自定义键盘
通过设置UITextField
的inputView
属性可以实现自定义键盘。例如,可自定义一个UIDatePicker
作为生日选择器。
- (void)setUp {
UIDatePicker *datePicker = [[UIDatePicker alloc] init];
datePicker.datePickerMode = UIDatePickerModeDate;
datePicker.locale = [NSLocale localeWithLocaleIdentifier:@"zh"];
[datePicker addTarget:self action:@selector(dateChange:) forControlEvents:UIControlEventValueChanged];
self.inputView = datePicker;
}
- (void)dateChange:(UIDatePicker *)datePicker {
NSDateFormatter *fmt = [[NSDateFormatter alloc] init];
fmt.dateFormat = @"yyyy-MM-dd";
self.text = [fmt stringFromDate:datePicker.date];
}
3. KVC的底层实现
键值编码(KVC)可以直接操作对象的属性,简化代码。在字典转模型时常用。
[model setValuesForKeysWithDictionary:dict];
其底层步骤:
- 遍历字典中的所有键值对。
- 使用
setValue:forKey:
为模型对象的属性赋值。
底层实现如下:
// 模型对象的属性赋值实现逻辑
- (void)setValue:(id)value forKey:(NSString *)key {
if ([self respondsToSelector:NSSelectorFromString(setterMethodName)]) {
// 1. 查找模型中是否有`set<Key>:`方法,如果存在则调用
[self performSelector:NSSelectorFromString(setterMethodName) withObject:value];
} else if ([self respondsToSelector:NSSelectorFromString(key)]) {
// 2. 否则查找模型中是否有键名相同的属性,存在则直接赋值
[self setValue:value forKeyProperty:key];
} else if ([self respondsToSelector:NSSelectorFromString(underscoreKey)]) {
// 3. 否则查找模型中是否有`_`开头的属性,存在则直接赋值
[self setValue:value forKeyUnderscoreProperty:underscoreKey];
} else {
// 4. 都不存在则抛出异常
@throw [NSException exceptionWithName:@"NSUnknownKeyException" reason:@"Unknown key" userInfo:nil];
}
}
三、通过Storyboard加载控制器
使用Storyboard可以简化UI设计和控制器管理。
// 加载Storyboard文件
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Main" bundle:nil];
// 创建Storyboard描述的控制器
UIViewController *vc = [storyboard instantiateInitialViewController];
通过标识符创建控制器:
UIViewController *vc = [storyboard instantiateViewControllerWithIdentifier:@"yourIdentifier"];
四、通过XIB创建控制器
通过XIB文件,可以自定义控制器的视图。具体步骤如下:
- 设置XIB文件的File's Owner为对应的控制器。
- 通过连线指定控制器的View。
在代码中使用如下:
// 在AppDelegate中创建控制器
XMGViewController *vc = [[XMGViewController alloc] initWithNibName:nil bundle:nil];
self.window.rootViewController = vc;
[self.window makeKeyAndVisible];
底层逻辑:
- 优先查找指定
nibName
的XIB文件。 - 如果
nibName
为空,则根据类名寻找对应的XIB文件。 - 如果都未找到,则生成一个空的
UIView
。
五、控制器的view创建
1. loadView方法
loadView
方法在第一次访问控制器的view时调用,用来加载控制器的view,可以通过重写这个方法自定义view。
- (void)loadView {
// 必须手动创建控制器的view
self.view = [[UIView alloc] init];
self.view.backgroundColor = [UIColor whiteColor];
}
2. xib加载控制器的view
通过init方法会调用initWithNibName:bundle:
方法。如果nibName
为空,会先查找同名的XIB文件。
3. 控制器view延迟加载
控制器的view是延迟加载的,也就是懒加载。只有当第一次访问view
属性时,才会调用loadView
方法。
- (UIView *)view {
if (!_view) {
[self loadView];
[self viewDidLoad];
}
return _view;
}
4. 控制器view默认是几乎透明的
创建的控制器view默认是透明的,只有部分透明度,并且是最下层的view。
六、导航控制器的基本使用
导航控制器(UINavigationController)用于在多个视图控制器之间进行层级导航。
1. 设置根控制器
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
// 创建导航控制器的根控制器
UIViewController *vc = [[OneViewController alloc] init];
UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:vc];
self.window.rootViewController = nav;
[self.window makeKeyAndVisible];
return YES;
}
2. 导航控制器的子控制器
导航控制器管理的子控制器可以直接通过navigationController
属性访问其导航控制器,并进行页面跳转。
// 跳转到第二个界面
- (IBAction)jump2Two:(id)sender {
TwoViewController *two = [[TwoViewController alloc] init];
[self.navigationController pushViewController:two animated:YES];
}
3. initWithRootViewController底层实现
initWithRootViewController
方法实际上调用了导航控制器的push
方法,将根控制器作为其第一个控制器。
UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:vc];
// 调用push方法
// [nav pushViewController:vc animated:YES];
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步