IOS学习笔记 -- UIPickerView 、UIDatePicker 以及多控制器管理

一.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列的第row行
- (void)selectRow:(NSInteger)row inComponent:(NSInteger)component animated:(BOOL)animated;
// 获得第component列的当前选中的行号
- (NSInteger)selectedRowInComponent:(NSInteger)component;

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;

二.UIDatePicker
1.常见属性
// datePicker的显示模式
@property (nonatomic) UIDatePickerMode datePickerMode;
// 显示的区域语言
@property (nonatomic, retain) NSLocale *locale;

2.监听UIDatePicker的选择
* 因为UIDatePicker继承自UIControl,所以通过addTarget:...监听

三.pch文件
1.pch文件应用场景:
1>.用来定义一些全局的宏
2>.用来导入一些全局都能用到的头文件
3>.用来自定义log

2.其他
__OBJC__这个宏,在所有的.m和.mm文件中默认就定义了这个宏,如果这个全局的头文件或者宏只需要在.m或者.mm文件中使用,请把该头文件或宏写到#ifdef __OBJC__ 中
在开发中分为两个阶段
1>.开发调试阶段:需要打印Log调试程序;处于调试阶段,系统会自动定义一个名称为DEBUG的宏
2>.发布阶段:不需要打印Log,因为Log很占用资源,并且用户看不懂Log;处于发布阶段,系统会自动删除名称为DEBUG的宏

3.自定义Log:
#ifdef DEBUG
#define NJLog(...) NSLog(__VA_ARGS__)
#else
#define NJLog(...)
#endif

四.UIApplication
1.UIApplication对象是应用程序的象征,每一个应用都有自己的UIApplication对象,而且是单例对象
UIApplication *app = [UIApplication sharedApplication];
IOS程序启动完毕后,创建的第一个对象就是UIApplication对象

2.利用UIApplication对象,能进行一些应用级别的操作
// 设置应用程序图标右上角的红色提醒数字
app.applicationIconBadgeNumber = 9;
// 设置联网指示器的可见性
app.isNetworkActivityIndicatorVisible = YES;
// 管理状态栏
UIApplication 和 UIViewController 管理状态栏的区别:
1>.通过UIViewController管理,每一个UIViewController都可以拥有自己不同的状态栏;
2>.通过UIApplication管理,一个应用程序的状态栏都由它统一管理,且可设置动画
如果想利用UIApplication来管理状态栏,首先得修改Info.plist的设置,View controller-based status bar appearance 设置为 NO;
[app setStatusBarStyle:UIStatusBarStyleLightContent animated:YES];
// openURL:方法
// 打开一个网页资源
[app openURL:[NSURL URLWithString:@"http://www.baidu.com"]];
// 打电话
[app openURL:[NSURL URLWithString:@"tel://10086"]];
// 发短信
[app openURL:[NSURL URLWithString:@"sms://10086"]];
// 发邮件
[app openURL:[NSURL URLWithString:@"mailto://12345@qq.com"]];

3.UIApplication 和 delegate
所有的移动操作系统都有个致命的缺点:app很容易受到打扰。比如一个来电或者锁屏会导致app进入后台甚至被终止;这时UIApplication会通知它的delegate对象,让delegate代理来处理这些系统事件.
delegate可处理的事件包括:
1>.应用程序的生命周期事件(如程序启动和关闭)
2>.系统事件(如来电)
3>.内存警告

四.程序启动的完整过程
1.main函数

2.UIApplicationMain(argc, argv, NSString NSString *principalClassName, NSString *delegateClassName)
* 创建UIApplication对象: principalClassName: 指定应用程序类名(app的象征),该类必须是UIApplication(或子类)。如果为nil,则用UIApplication类作为默认值
* 创建UIApplication的delegate对象: delegateClassName:指定应用程序的代理类,该类必须遵守UIApplicationDelegate协议

3.开启事件循环
1>.delegate对象开始处理(监听)系统事件(没有storyboard)
* 程序启动完毕的时候, 就会调用代理的application:didFinishLaunchingWithOptions:方法
* 在application:didFinishLaunchingWithOptions:中创建UIWindow
* 创建和设置UIWindow的rootViewController
* 显示窗口

2>.根据Info.plist获得最主要storyboard的文件名,加载最主要的storyboard(有storyboard)
* 创建UIWindow
* 创建和设置UIWindow的rootViewController
* 显示窗口

4.程序正常退出时UIApplicationMain函数才返回

五.UIWindow
1.iOS程序启动完毕后,创建的第一个视图控件就是UIWindow,一个iOS程序之所以能显示到屏幕上,完全是因为它有UIWindow

2.添加UIView到UIWindow中两种常见方式:
1>.将控制器的view添加到UIWindow上
[self.window addSubview:viewController.view];
该方法存在问题:
1).当view发生一些事件的时候,通知控制器, 但是控制器以及销毁了,所以可能出现未知错误(野指针错误)
2).当发生旋转事件的时候,UIApplication对象会将旋转事件传递给UIWindow,UIWindow又会将旋转事件传递它的根控制器,由根控制器决定是否需要旋转
2>.设置UIWindow的根控制器(建议使用下面这种方式)
self.window.rootViewController = viewController;

3.常用方法
// 让当前UIWindow变成keyWindow(主窗口)
- (void)makeKeyWindow;
// 让当前UIWindow变成keyWindow,并显示出来
- (void)makeKeyAndVisible;
// 获取应用程序的主窗口
[UIApplication sharedApplication].keyWindow
// 获取所有的window
[UIApplication sharedApplication].windows
一个应用程序只能有一个主窗口
主窗口和此窗口的区别: IOS7以前,只有主窗口才能输入内容(响应键盘的输入事件)

六.控制器的创建方式
1.第一种创建方式:代码创建
NJViewController *vc = [[NJViewController alloc] init];
self.window.rootViewController = vc;

2.第二种创建方式:storyboard创建
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Test" bundle:nil];
// 创建storyboard中箭头指向的控制器
NJViewController *vc = [storyboard instantiateInitialViewController];
// UIViewController *vc = [storyboard instantiateViewControllerWithIdentifier:@"two"];
self.window.rootViewController = vc;

3.第三种创建方式:xib创建
// 设置xib File's Owner 的 Custom Class 为NJViewController, 再连线到view
NJViewController *vc = [[NJViewController alloc] initWithNibName:@"One" bundle:nil];
self.window.rootViewController = vc;

七.view的创建方式
1.没有同名xib情况下:如果没有xib和storyboard, 会自动创建一个空白的view做为控制器的view
NJViewController *vc = [[NJViewController alloc] init];

2.通过storyboard创建:如果通过storyboard创建, 会创建箭头指向view做为控制器的view
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Test" bundle:nil];
NJViewController *vc = [storyboard instantiateInitialViewController];

3.有指定xib情况下创建:如果通过xib, 会创建xib中描述的view做为控制器的view
NJViewController *vc = [[NJViewController alloc] initWithNibName:@"One" bundle:nil];

4.有同名xib情况:如果有同名的xib, 会自动找到同名xib中描述的view做为控制器的view
NJViewController *vc = [[NJViewController alloc] init];

5.有同名去掉controll的情况:如果有有同名去掉Controller的xib, 会自动找到该xib的view做为控制器的view
NJViewController *vc = [[NJViewController alloc] init];

6.loadView:如果重写了控制器的loadview方法, 就不会去加载其他创建方法, 而是创建一个在loadView的view做为控制器的view
loadView一般用于自定义控制器的view
@implementation ViewController
- (void)loadView
{
self.view = [[UIView alloc] init];
}
@end

7.view创建方式优先级
loadView > 通过storyboard创建 > 有指定xib情况下创建 > 有同名去掉controll的情况 > 有同名xib情况 > 没有xib和storyboard
控制器view是延迟加载(懒加载)的

八.UINavigationController
1.UINavigationController的使用步骤
1>.初始化UINavigationController
UINavigationController *nav = [[UINavigationController alloc] init];
self.window.rootViewController = nav;
2>.设置UIWindow的rootViewController为UINavigationController
3>.根据具体情况,通过push方法添加对应个数的子控制器
OneViewController *one = [[OneViewController alloc] init];
[nav pushViewController:one animated:YES];

2.UINavigationController的子控制器
[[UINavigationController alloc] initWithRootViewController:one];
[nav pushViewController:one animated:YES];
[nav addChildViewControllers:one];
nav.viewControllers = @[one];
// 只要当前控制器是导航控制器的子控制器,就快要通过该属性直接获取到当前控制器所在的导航控制器
self.navigationController
// 获取栈顶控制器
nav.topViewController
// 移除当前栈顶的控制器
[self.navigationController popViewControllerAnimated:YES];
// 移除除了栈底控制器的所有控制器
[self.navigationController popToRootViewControllerAnimated:YES];

3.修改导航栏的内容
// 左上角的返回按钮
self.navigationController.backBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"返回" style:UIBarButtonItemStylePlain target:nil action:nil];
// 中间的标题视图
self.navigationItem.titleView = [[UISwitch alloc] init];
// 中间的标题文字
self.navigationItem.title = @"";
// 左上角的视图
self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:nil action:nil];
// 右上角的视图
self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemCamera target:nil action:nil];

九.控制器的生命周期
loadView(加载控制器的view时调用) -> viewDidLoad(控制器的view加载完毕时调用) -> viewWillAppear(控制器的view即将显示时调用) -> viewDidAppear(控制器的view完全显示时调用) -> viewWillDisappear(控制器的view即将消失时调用) -> viewDidDisappear(控制器的view完全消失时调用) -> didReceiveMemoryWarning(控制器接收到从UIApplication传来的内存警告时调用,询问view是否可以被销毁(view不在window上就可以销毁)) -> viewWillUnload(控制器的view即将销毁时调用) -> 销毁view(此时控制器的属性都没有被清理) -> viewDidUnload(控制器的view完全销毁时调用,清空控制器内不需要的属性) ->loadView(需要再次显示控制器是在调用) 往复循环

posted on 2014-06-05 19:42  问苍天  阅读(241)  评论(0编辑  收藏  举报