数据选择控件
-
数据选择控件?
- 帮助用户快速选择数据的控件。
- UIPickerView——显示一组或多组数据方便用户选择。
- UIDatePicker——显示一个日期组件方便用户选择。
-
UIPickerView——数据选择视图
- 作用:
- 从指定的数据源中选择数据。
- 通常以UITextField的inputView的形式出现(当选中某个文本框后,弹出键盘中显示该控件)。
- 注意:
- 使用PickerView之前需要指定数据源对象和代理对象。
- 需要使用到的两个协议:
UIPickerViewDataSource
数据源协议,UIPickerViewDelegate
数据源代理协议。
- 随机生成数字
arc4random()
:- 这是个C语言函数。
- 随机生成一个无符号整数(0或所有正整数)。
- 随机生成一个0~n之间的数字:
arc4random() % (n + 1)
arc4random_uniform(u_int32_t)
- 作用:
// UIPickerView的数据源方法 @required
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView; // 设置UIPickerView共有几列
- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component; // 设置每列中有几行
// UIPickerView的代理方法 @optional
- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component; // 每行的数据内容
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component; // 监听PickerView的选择事件
- (UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(UIView *)view; // 自定义每行显示的样式
// UIPickerView的对象方法
- (void)selectRow:(NSInteger)row inComponent:(NSInteger)component animated:(BOOL)animated; // 选中指定component列中的row行,滚动到指定的行,不会触发代理方法
- (NSInteger)selectedRowInComponent:(NSInteger)component; // 返回当前列的选中行的索引
- (void)reloadAllComponents; // 重新加载所有列的数据
- (void)reloadComponent:(NSInteger)component; // 重新加载指定列的数据
-
UIDatePicker——方便用户选择日期
-
作用:
- 方便用户日期选择,并保证日期格式正确。
- 通常以UITextField的inputView的形式出现。
-
自定义文本框的弹出键盘:
- 通过设置UITextField的inputView属性来修改当文本框获得焦点后,弹出什么控件。
- 设置该属性的值为UIDatePicker控件(动态创建一个UIDatePicker控件,无需设置高宽),这样就可以实现当文本框获得焦点后,自定义弹出键盘了。
-
自定义键盘上的工具控件:
- 设置文本框的inputAccessoryView属性即可。
- 工具条的使用:UIToolbar(barTintColor,从iOS7开始;backgroundColor继承自UIView,从iOS2开始)。
- Accessory,表示“附件”、“装饰品”的意思。
- 在UIToolbar中只能放UIBarButtonItem,工具条一般用在键盘上面。
- 设置某个BarButtonItem显示在最右边:在最右边的BarButtonItem之前插入一个BarButtonItem,并设置该BarButtonItem的Identifier的值为Flexible Space。
- 工具条一般用在键盘上面。
- 创建好工具条以后要设置工具条的frame。
-
@property (nonatomic) UIDatePickerMode datePickerMode; // 日期选择模式,默认UIDatePickerModeDateAndTime
@property (nonatomic, retain) NSLocale *locale; // 语言环境,默认[NSLocale currentLocale]
@property (nonatomic, retain) NSDate *date; // 默认是创建控件时的当前系统日期
@property (nonatomic, retain) NSDate *minimumDate; // 指定min/max日期范围。默认为nil。如果 min > max,指定的数值会被忽略。在UIDatePickerModeCountDownTimer模式无效
@property (nonatomic, retain) NSDate *maximumDate; // 默认为nil
@property (nonatomic) NSTimeInterval countDownDuration; // 用于UIDatePickerModeCountDownTimer模式,默认是0.0,最大不能超过23:59 (86,399 秒)。设置数值以分钟为单位
@property (nonatomic) NSInteger minuteInterval; // 间隔分钟,最小1,最大30
- (void)setDate:(NSDate *)date animated:(BOOL)animated; // 设置日期(动画)
程序的启动原理
-
项目中的常见文件?
- xxxxTest文件夹用来做单元测试。
- Products目录:在Mac程序下,生产的可执行文件app会存放到该目录下,iOS程序产生的是ipa文件,Products目录对于iOS程序来说意义不大。
- Info.plist,全局配置文件,非常重要,不能删除,注意自己创建的plist文件中不要包含Info关键字。Info.plist中的一些配置项:
- Bundle display name(在Xcode6中叫做“Bundle name”),表示软件装到手机上后,显示的名称。当修改了该名称后,为了保证有效,点击Product->Clean,同时将软件从模拟器中卸载掉,然后再重新运行。
- Bundle Identifier,app的唯一标示。
- Bundle Version,每次发布软件的版本号。
- Main storyboard file base name,对应的就是选中“项目”->“General”->“Deployment Info”->“Main Interface”中的设置。
- Supported interface orientations,标识设备所支持的方向,对应的选中“项目”->“General”->“Deployment Info”->“Device Orientation”。iPhone只支持三种方向,Portrait(竖屏)、Landscape Left(横屏向左)、Landscape Right(横屏向右)。
- Info.plist文件本质就是一个xml文件。
- pch文件:(Prefix Header File)(头文件):
- 遇到的问题:①整个项目中很多地方都在使用某个类的头文件;②整个项目中很多地方都在使用同一个“宏”;③在项目中很多地方用到了NSLog()函数,想快速清除。
- 解决上面的问题,可以通过使用pch文件,pch文件就是一个头文件(类似于*.h文件)。
- 注意:pch文件的特点,项目中的所有其他代码文件无需导入该pch文件,默认就都可以访问(其他文件无需手动#import该pch文件就能使用)。
- 主要作用:可以放一些公用的宏定义;把公共的Model类的#import导入写到pch文件中;自定义NSLog()(例如:#define LNLog(...) NSLog(VA_ARGS))。
- 在Xcode6.1中,默认没有创建pch文件,创建方式:"New File"->"Other"->"PCH File"->"PrefixHeader.pch"。
- 选中项目->Build Setting->All->搜索"prefix head"->修改Prefix Header的内容为:
"$(SRCROOT)/$(PRODUCT_NAME)/PrefixHeader.pch"
或者"$(SRCROOT)/对应的文件夹名/PrefixHeader.pch"
。
- 补充,程序开发阶段分为:
- 调试阶段:写代码、调错误,需要使用NSLog(),同时在调试阶段系统会自定义一个叫做DEBUG的宏。
- 发布阶段:写好的代码生成ipa等压缩文件,上传到AppStore,安装到用户设备上,不需要NSLog(),同时系统会自动删除叫做DEBUG的宏。
-
UIApplication对象介绍?
- 一个UIApplication代表是一个应用程序,而且是单例的,用来封装整个应用程序的一个对象,比如当应用程序执行到某个时期要做什么,生命周期等。
- 获取UIApplication对象:
[UIApplication sharedApplication];
(单例的)。 - 当一个iOS程序启动后,首先创建的第一个对象就是UIApplication对象。
- 利用UIApplication可以做一些应用级别的操作:
- 如应用程序右上角的角标;
- 联网操作时,状态栏上的等待图标指示器;
- 利用UIApplication打开某个资源;
- 通过UIApplication管理状态栏,iOS7开始状态栏默认交给了控制器来管理,如果希望通过UIApplication来管理,需要在Info.plist文件中增加一个配置项
* View controller-based status bar appearance = NO
。
// 获取UIApplication对象
UIApplication *app = [UIApplication sharedApplication];
// iOS8系统要求设置通知的时候必须经过用户许可
UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeBadge categories:nil];
[app registerUserNotificationSettings:settings];
// 设置右上角,有10条消息
app.applicationIconBadgeNumber = 10;
// 联网操作时,状态栏上的等待图标指示器,waiting图标
app.networkActivityIndicatorVisible = YES;
// 利用UIApplication打开某个资源,系统会自动根据协议识别使用某个app打开
[app openURL:[NSURL URLWithString:@"http://www.baidu.com"]];
// 设置状态栏是否隐藏
app.statusBarHidden = YES;
-
UIApplicationDelegate介绍?
- 新建完项目以后AppDelegate文件,就是UIApplication的代理对象,并且该代理对象已经被设置好了,无需我们手动设置。
- AppDelegate的主要作用就是处理(监听)应用程序本身的各种事件:应用程序启动完毕,应用程序进入后台,应用程序进入前台,内存警告等,都是应用程序自身的一些事件。
- 要想成为UIApplication的代理对象,必须遵守:UIApplicationDelegate协议。
// app第一次启动完毕后就会调用(当程序启动后会显示一张启动图片, 当这个图片显示完毕, 消失后, 就开始调用这个方法)
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions;
// 当程序进入后台时,调用该方法,在这个方法中可以做一些保存当前程序数据, 暂停程序的操作
- (void)applicationDidEnterBackground:(UIApplication *)application;
// 当程序再次进入前台的时候调用
- (void)applicationWillEnterForeground:(UIApplication *)application;
// 当发生内存警告时触发该事件
- (void)applicationDidReceiveMemoryWarning:(UIApplication *)application;
- UIApplicationMain函数介绍?
- 方法名:
int UIApplicationMain(int argc, char *argv[], NSString *principalClassName, NSString *delegateClassName);
2. 参数介绍:
* argc:使用main函数的argc即可。
* argv:使用main函数的argv即可。
* principalClassName:指定应用程序类名(app的象征),该类必须是UIApplication(或子类),如果为nil,则用UIApplication类作为默认值。
* delegateClassName:指定应用程序的代理类,UIApplicationDelegate协议中定义的方法,在该类中实现。
3. UIApplicationMain函数会:
* 根据principalClassName创建UIApplication对象。
* 根据delegateClassName创建一个delegate对象,并将该delegate对象赋值给UIApplication对象中的delegate对象。
* 代理参数必须传递,如果传nil,则显示“黑屏”。
// 默认调用方式
UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
// 等价于
UIApplicationMain(argc, argv, @"UIApplication", @"AppDelegate");
-
iOS程序启动过程?
- 打开程序。
- 调用main函数。
- 在main函数中调用:UIApplicationMain()函数。
- 在UIApplicationMain()函数中:
- 创建UIApplication对象。
- 创建AppDelegate代理对象。
- 将AppDelegate代理对象设置给UIApplication对象。
- 在UIApplicationMain()函数开启一个“死循环(事件循环)”,所以程序不会退出,可以任意使用,在这个“死循环(事件循环)”中程序不断监听用户的各种事件,依次处理(依靠“事件队列”实现)。
- 程序启动完毕,触发
application:didFinishLaunchingWithOptions:
事件。
- 程序退出。
- 在UIApplicationMain()函数中:
-
UIWindow对象?
- UIWindow是一中特殊的UIView,UIWindow也是继承自UIView。
- 通常一个app只会有一个UIWindow对象。
- iOS程序启动完毕后,创建的第一个视图控件就是UIWindow,接着创建控制器的view,最后将控制器的view添加到UIWindow上,于是控制器的view就显示在屏幕上了。
- 一个iOS程序之所以能显示到屏幕上,完全是因为它有UIWindow。
- 创建过程UIWindow->UIViewController->UIView->把UIView加到UIWindow对象中。
- 将控制器的view添加到UIWindow中:
- 方式一:直接把控制器的view添加到UIWindow中,此方法不推荐,因为当方法执行完毕后控制器就释放了,但是控制器的view还在,当手机旋转的时候,界面中的内容不会跟着旋转,UIView中的各个子控件的事件监听程序都写在了一个类中,无法分为多个控制器来管理。
- 方式二:通过设置UIWindow的根控制器的方式(推荐)。
- 如果不使用控制器,直接把控件添加到UIWindow中行不行?可以的,但是不推荐。因为如果把所有控件都直接加到UIWindow上,那么很多个界面,每个界面的各种事件监听都交给了同一个类来处理了。
- 总结:UIWindow就一个作用“显示界面”,将来是通过切换不同的控制器view分别显示到UIWindow上。
-
总结程序启动的完整过程?
- 没有storyboard文件:
- 调用main函数。
- 调用UIApplicationMain函数。
- 创建UIApplication对象,AppDelegate对象。
- 设置UIApplication对象的代理是AppDelegate对象。
- AppDelegate对象开始监听“系统事件(应用程序的事件)”,进入“事件循环”。
- 程序启动完毕后调用
application: didFinishLaunchingWithOptions:
方法。 -
application: didFinishLaunchingWithOptions:
方法中创建:UIWindow、控制器、设置UIWindow的根控制器是刚才创建的控制器、显示UIWindow。
- 有storyboard文件:
- 调用main函数。
- 调用UIApplicationMain函数。
- 创建UIApplication对象、AppDelegate对象。
- 设置UIApplication对象的代理是AppDelegate对象。
- AppDelegate对象开始监听“系统事件(应用程序的事件)”,进入“事件循环”。
- 程序启动完毕后调用
application: didFinishLaunchingWithOptions:
方法。 -
application: didFinishLaunchingWithOptions:
方法中创建:- 系统自动创建UIWindow对象。
- 根据Info.plist文件配置(Main Interface),找到需要加载的storyboard文件(Main.storyboard)。
- 找到Main.storyboard中的Is Initial View Controller对应的控制器类,创建该控制器对象。
- 根据storyboard中的配置,创建控制器对应的view。
- 设置UIWindow的根控制器(rootViewController)为刚才创建的控制器。
- 显示UIWindow(
[self.window makeKeyAndVisible];
)。
- 没有storyboard文件: