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

作者: 冷漠叻荭颜 | 来源:发表于2015-03-27 01:10 被阅读379次

    数据选择控件


    • 数据选择控件?

      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];)。

    相关文章

      网友评论

      本文标题:UI控件进阶1——程序启动原理

      本文链接:https://www.haomeiwen.com/subject/bocnxttx.html