UI控件进阶1——程序启动原理

数据选择控件


  • 数据选择控件?

    1. 帮助用户快速选择数据的控件。
    2. UIPickerView——显示一组或多组数据方便用户选择。
    3. UIDatePicker——显示一个日期组件方便用户选择。

  • UIPickerView——数据选择视图

    1. 作用:
      • 从指定的数据源中选择数据。
      • 通常以UITextField的inputView的形式出现(当选中某个文本框后,弹出键盘中显示该控件)。
    2. 注意:
      • 使用PickerView之前需要指定数据源对象和代理对象。
      • 需要使用到的两个协议:UIPickerViewDataSource数据源协议,UIPickerViewDelegate数据源代理协议。
    3. 随机生成数字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——方便用户选择日期

    1. 作用:

      • 方便用户日期选择,并保证日期格式正确。
      • 通常以UITextField的inputView的形式出现。
    2. 自定义文本框的弹出键盘:

      • 通过设置UITextField的inputView属性来修改当文本框获得焦点后,弹出什么控件。
      • 设置该属性的值为UIDatePicker控件(动态创建一个UIDatePicker控件,无需设置高宽),这样就可以实现当文本框获得焦点后,自定义弹出键盘了。
    3. 自定义键盘上的工具控件:

      • 设置文本框的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; // 设置日期(动画)

程序的启动原理

  • 项目中的常见文件?

    1. xxxxTest文件夹用来做单元测试。
    2. Products目录:在Mac程序下,生产的可执行文件app会存放到该目录下,iOS程序产生的是ipa文件,Products目录对于iOS程序来说意义不大。
    3. 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文件。
    4. 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"
    5. 补充,程序开发阶段分为:
      • 调试阶段:写代码、调错误,需要使用NSLog(),同时在调试阶段系统会自定义一个叫做DEBUG的宏。
      • 发布阶段:写好的代码生成ipa等压缩文件,上传到AppStore,安装到用户设备上,不需要NSLog(),同时系统会自动删除叫做DEBUG的宏。

  • UIApplication对象介绍?

    1. 一个UIApplication代表是一个应用程序,而且是单例的,用来封装整个应用程序的一个对象,比如当应用程序执行到某个时期要做什么,生命周期等。
    2. 获取UIApplication对象:[UIApplication sharedApplication];(单例的)。
    3. 当一个iOS程序启动后,首先创建的第一个对象就是UIApplication对象。
    4. 利用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介绍?

    1. 新建完项目以后AppDelegate文件,就是UIApplication的代理对象,并且该代理对象已经被设置好了,无需我们手动设置。
    2. AppDelegate的主要作用就是处理(监听)应用程序本身的各种事件:应用程序启动完毕,应用程序进入后台,应用程序进入前台,内存警告等,都是应用程序自身的一些事件。
    3. 要想成为UIApplication的代理对象,必须遵守:UIApplicationDelegate协议。
// app第一次启动完毕后就会调用(当程序启动后会显示一张启动图片, 当这个图片显示完毕, 消失后, 就开始调用这个方法)
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions;
// 当程序进入后台时,调用该方法,在这个方法中可以做一些保存当前程序数据, 暂停程序的操作
- (void)applicationDidEnterBackground:(UIApplication *)application;
// 当程序再次进入前台的时候调用
- (void)applicationWillEnterForeground:(UIApplication *)application;
// 当发生内存警告时触发该事件
- (void)applicationDidReceiveMemoryWarning:(UIApplication *)application;

  • UIApplicationMain函数介绍?
    1. 方法名:
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程序启动过程?

    1. 打开程序。
    2. 调用main函数。
    3. 在main函数中调用:UIApplicationMain()函数。
      • 在UIApplicationMain()函数中:
        • 创建UIApplication对象。
        • 创建AppDelegate代理对象。
        • 将AppDelegate代理对象设置给UIApplication对象。
        • 在UIApplicationMain()函数开启一个“死循环(事件循环)”,所以程序不会退出,可以任意使用,在这个“死循环(事件循环)”中程序不断监听用户的各种事件,依次处理(依靠“事件队列”实现)。
        • 程序启动完毕,触发application:didFinishLaunchingWithOptions:事件。
      • 程序退出。

  • UIWindow对象?

    1. UIWindow是一中特殊的UIView,UIWindow也是继承自UIView。
    2. 通常一个app只会有一个UIWindow对象。
    3. iOS程序启动完毕后,创建的第一个视图控件就是UIWindow,接着创建控制器的view,最后将控制器的view添加到UIWindow上,于是控制器的view就显示在屏幕上了。
    4. 一个iOS程序之所以能显示到屏幕上,完全是因为它有UIWindow。
    5. 创建过程UIWindow->UIViewController->UIView->把UIView加到UIWindow对象中。
    6. 将控制器的view添加到UIWindow中:
      • 方式一:直接把控制器的view添加到UIWindow中,此方法不推荐,因为当方法执行完毕后控制器就释放了,但是控制器的view还在,当手机旋转的时候,界面中的内容不会跟着旋转,UIView中的各个子控件的事件监听程序都写在了一个类中,无法分为多个控制器来管理。
      • 方式二:通过设置UIWindow的根控制器的方式(推荐)。
    7. 如果不使用控制器,直接把控件添加到UIWindow中行不行?可以的,但是不推荐。因为如果把所有控件都直接加到UIWindow上,那么很多个界面,每个界面的各种事件监听都交给了同一个类来处理了。
    8. 总结:UIWindow就一个作用“显示界面”,将来是通过切换不同的控制器view分别显示到UIWindow上。

  • 总结程序启动的完整过程?

    1. 没有storyboard文件:
      • 调用main函数。
      • 调用UIApplicationMain函数。
      • 创建UIApplication对象,AppDelegate对象。
      • 设置UIApplication对象的代理是AppDelegate对象。
      • AppDelegate对象开始监听“系统事件(应用程序的事件)”,进入“事件循环”。
      • 程序启动完毕后调用application: didFinishLaunchingWithOptions:方法。
      • application: didFinishLaunchingWithOptions:方法中创建:UIWindow、控制器、设置UIWindow的根控制器是刚才创建的控制器、显示UIWindow。
    2. 有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];)。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,117评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,328评论 1 293
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,839评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,007评论 0 206
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,384评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,629评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,880评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,593评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,313评论 1 243
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,575评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,066评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,392评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,052评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,082评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,844评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,662评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,575评论 2 270

推荐阅读更多精彩内容