day10-程序的启动原理

来源:互联网 发布:数据定义语言包括哪些 编辑:程序博客网 时间:2024/06/16 10:30

前言

掌握:
0、UIPickerView、UIDatePicker
1、info.plist和pch文件的作用
2、UIApplication的常见使用
3、AppDelegate的代理方法
4、UIApplication、AppDelagate、UIWindow、UIViewController的关系

这里写图片描述

5、iOS程序的完整启动过程

一、info.plist常见的属性

运行期的配置;项目中还有一个infoplist.strings文件,跟info.plist文件的本地化相关

二、pch头文件

这里写图片描述

pch头文件的内容能够被项目中的其他所有源文件共享和访问
1.一般在pch文件定义一些全局的宏
2、在pch文件中添加预处理指令、然后在项目中使用log(。。)来输出日志信息;这样可以在发布应用的时候,一次性将NsLog语句移除;通常在调试模式下,才有定义debug.

三、UIApplication(应用程序的象征)

1、每一个应用都有自己的UIApplication对象,而且是单例的;

[UIApplication sharedApplication]

1》一个iOS程序启动后创建的第一个对象,就是UIApplication对象
2》利用UIApplication对象可以进行一些应用级的操作
2、UIApplication的常用属性

@property(nonatomic,getter=isNetworkActivityIndicatorVisible) BOOL networkActivityIndicatorVisible __TVOS_PROHIBITED; // showing network spinning gear in status bar. default is NO 设置联网指示器的可见行@property(nonatomic) NSInteger applicationIconBadgeNumber __TVOS_PROHIBITED;  // set to 0 to hide. default is 0. In iOS 8.0 and later, your application must register for user notifications using -[UIApplication registerUserNotificationSettings:] before being able to set the icon badge.设置应用程序图标右上角的红色提醒数字

3、openURL : 方法

- (BOOL)openURL:(NSURL*)url NS_EXTENSION_UNAVAILABLE_IOS("");//url    A URL (Universal Resource Locator). UIKit supports many common schemes, including the http, https, tel, facetime, and mailto schemes. You can also employ custom URL schemes associated with apps installed on the device.//打电话UIApplication *app= [UIApplication sharedApplication];[app openURL:[NSURL URLWithString:@"tel://10086"]];//发短信[app openURL:[NSURL URLWithString:@"sms://10086"]];//发邮件[app openURL:[NSURL URLWithString:@"mailto://12345@qq.com"]];//打开一个网页资源[app openURL:[NSURL URLWithString:@"http://ios.itcast.cn"]];

四、状态栏(2种管理方式)

通过UIViewController(每一个UIViewController都可以拥有自己不同的状态栏)、UIApplication管理(一个应用程序的状态栏都由它统一管理)
1、默认情况下,状态栏都是由UIViewController管理

- (UIStatusBarStyle)preferredStatusBarStyle NS_AVAILABLE_IOS(7_0) __TVOS_PROHIBITED; // Defaults to UIStatusBarStyleDefault- (BOOL)prefersStatusBarHidden NS_AVAILABLE_IOS(7_0) __TVOS_PROHIBITED; // Defaults to NO// Override to return the type of animation that should be used for status bar changes for this view controller. This currently only affects changes to prefersStatusBarHidden. 状态栏的可见性
1.VC中重写-(UIStatusBarStyle)preferredStatusBarStyle2、在viewDidload中调用:[self setNeedsStatusBarAppearanceUpdate];但是:当vc在nav中时,上面方法没用,vc中的preferredStatusBarStyle方法根本不用被调用。原因是,[self setNeedsStatusBarAppearanceUpdate]发出后,只会调用navigation controller中的preferredStatusBarStyle方法,vc中的preferredStatusBarStyley方法跟本不会被调用。解决方法:self.navigationController.navigationBar.barStyle = UIBarStyleBlack;或者定义一个nav bar的子类,在这个子类中重写preferredStatusBarStyle方法:

2、利用UIApplication管理状态栏
要修改info.plist的viewController based status bar appearance 属性

<key>UIViewControllerBasedStatusBarAppearance</key><false/>
1、在info.plist中,将View controller-based status bar appearance设为NO.2、在app delegate中:[UIApplication sharedApplication].statusBarStyle = UIStatusBarStyleLightContent;

五、 UIApplication和delegate

在app受到干挠(来电、锁屏)时,会产生些系统事件,让delegate处理这些系统事件
1、delegate 可处理的事件
1》应用程序的生命周期(程序启动、关闭): 处理苹果服务器推送的消息。
2》系统事件(来电)
3》内存警告

这里写图片描述

ps:获取焦点意味着,应用程序可以与用户进行交互

六、iOS程序的启动过程

/**  This function is called in the main entry point to create the application object and the application delegate and set up the event cycle.UIApplicationMain函数会根据principalClassName创建UIApplication对象,根据delegateClassName创建一个delegate对象,并将该delegate对象赋值给UIApplication对象中的delegate属性;接着会建立应用程序的Main Runloop(事件循环),进行事件的处理(首先会在程序完毕后调用delegate对象的application:didFinishLaunchingWithOptions:方法);程序正常退出时UIApplicationMain函数才返回*/UIKIT_EXTERN int UIApplicationMain(int argc, char *argv[], NSString * __nullable principalClassName, NSString * __nullable delegateClassName);///**参数: principalClassName :The name of the UIApplication class or subclass. If you specify nil, UIApplication is assumed. */

七、UIWindow(特殊的UIView,通常一个app中只会有一个UIWindow)

键盘也是UIWindow。使用Xcode的图层即可清晰查看。

p s:一个iOS程序之所以能显示到屏幕上,完全是因为它有UIWindow;也就说,没有UIWindow,就看不见任何UI界面

2、添加UI View到UIWindow中的两种常用方式

- (void)addSubview:(UIView *)view;//直接将UIView添加到UIWindow中,但并不会理会view对应的UIViewController
@property(nullable, nonatomic,strong) UIViewController *rootViewController NS_AVAILABLE_IOS(4_0);  // default is nil;自动将rootViewController的view添加到UIWindow中,负责管理rootViewController的生命周期

3、常用方法
makeKeyWindow、makeKeyAndVisible

- (void)makeKeyWindow;//让当前UIWindow变成keyWindow(主窗口)Makes the receiver the main window.- (void)makeKeyAndVisible; // convenience. most apps call this to show the main window and also make it key. otherwise use view hidden property;Makes the receiver the key window and visible.让当前UIWindow变成keyWindow,并显示出来-

4、UIWindow的对象获取
获取UIWindow

/**方式一:@property(nonatomic,readonly) NSArray<__kindof UIWindow *>  *windows;  */[UIApplication sharedApplication].windows//在本应用中打开的UIWindow列表,这样就可以接触应用中的任何一个UIView对象(平时输入文字弹出的键盘,就处在一个新的UIWindow中)/** 方式二:@property(nullable, nonatomic,readonly) UIWindow *keyWindow;*/[UIApplication sharedApplication].keyWindow//用来接收键盘以及非触摸类的消息事件的UIWindow,而且程序中每个时刻只能有一个UIWindow是keyWindow。如果某个UIWindow内部的文本框不能输入文字,可能是因为这个UIWindow不是keyWindow/** 方式三:@property(nullable, nonatomic,readonly) UIWindow     *window;*/view.window//获得某个UIView所在的UIWindow

八、四大对象关系图

这里写图片描述

正文

案例 1、点菜系统

这里写图片描述

///  ViewController.m//  20160331-点菜系统////  Created by devzkn on 3/31/16.//  Copyright © 2016 hisun. All rights reserved.//#import "ViewController.h"@interface ViewController () <UIPickerViewDataSource,UIPickerViewDelegate>@property (weak, nonatomic) IBOutlet UILabel *mainLabel;@property (weak, nonatomic) IBOutlet UILabel *drinkLabel;@property (nonatomic,strong) NSArray *foodsData;@property (weak, nonatomic) IBOutlet UILabel *fruitLabel;@property (weak, nonatomic) IBOutlet UIPickerView *pickerView;@end@implementation ViewController-(NSArray *)foodsData{    if (nil == _foodsData) {        _foodsData = [NSArray arrayWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"foods" ofType:@"plist"]];    }    return _foodsData;}- (void)viewDidLoad {    [super viewDidLoad];    //初始化label数据    [self.fruitLabel setText:self.foodsData[0][0]];    [self.mainLabel setText:self.foodsData[1][0]];    [self.drinkLabel setText:self.foodsData[2][0]];}/** 产生随机的下标 */- (IBAction)randomMenu {    /**  方式一 *///    int row0 = arc4random_uniform([self.foodsData[0] count]);//    int row1 = arc4random_uniform([self.foodsData[1] count]);//    int row2 = arc4random_uniform([self.foodsData[2] count]);//    [self pickerView:self.pickerView didSelectRow:row0 inComponent:0];//    [self pickerView:self.pickerView didSelectRow:row1 inComponent:1];//    [self pickerView:self.pickerView didSelectRow:row2 inComponent:2];//    //切换pickerView的选择的行,//    [self.pickerView selectRow:row0 inComponent:0 animated:YES];//Selects a row in a specified component of the picker view.//    [self.pickerView selectRow:row1 inComponent:1 animated:YES];//Selects a row in a specified component of the picker view.//    [self.pickerView selectRow:row2 inComponent:2 animated:YES];//Selects a row in a specified component of the picker view.    /**  方式二*/    for (int i = 0; i< self.foodsData.count; i++) {//i 代表分组下标        //获取旧的选择行        int oldRow = [self.pickerView selectedRowInComponent:i];//Returns the index of the selected row in a given component.        //计算行数        int row = oldRow;        while (oldRow == row) {            row = arc4random_uniform([self.foodsData[i] count]);        }        //更新label        [self pickerView:self.pickerView didSelectRow:row inComponent:i];        //更新选择的行        [self.pickerView selectRow:row inComponent:i animated:YES];    }}#pragma mark - UIPickerViewDataSource 协议方法// returns the number of 'columns' to display.- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView{    return self.foodsData.count;}// returns the # of rows in each component..- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component{    return [self.foodsData[component] count];}#pragma mark - UIPickerViewDelegate 代理方法细节实现- (nullable NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component __TVOS_PROHIBITED{       return self.foodsData[component] [row];}- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component __TVOS_PROHIBITED{    //避免魔法数组,可采用enum    switch (component) {        case 0:            [self.fruitLabel setText:self.foodsData[component][row]];            break;        case 1:            [self.mainLabel setText:self.foodsData[component][row]];            break;        case 2:            [self.drinkLabel setText:self.foodsData[component][row]];            break;    }}@end

02-国旗选择

这里写图片描述

#pragma mark -  UIPickerViewDelegate/**  通常用于自定义UIPickerTableView 的UIPickerTableViewTitleCell*/- (UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(nullable UIView *)view __TVOS_PROHIBITED{    HSFlagsCellView *cell = nil;    HSFlagsModel *model = self.flagsList[row];    if (view != nil) {        //代表有空循环使用的view        //只须设置下数据模型        cell =(HSFlagsCellView *) view;        [cell setFlagsModel:model];//数据装配    }else{        cell = [HSFlagsCellView pickerVieCellWithFlagsModel:model pickerView:pickerView];    }    NSLog(@" %d--%p",row,cell);    return cell;}- (CGFloat) pickerView:(UIPickerView *)pickerView rowHeightForComponent:(NSInteger)component{    return 44;}

03-省市联动

/** 设置分组的表格内容 */- (UIView *) pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(UIView *)view{    UILabel *label = nil;    if (view != nil) {        label = (UILabel *)view;    }else{        label = [[UILabel alloc]init];    }    NSString *text = nil;    if (component == 0) {        text =   [self.provincesList[row] name] ;        [label setBackgroundColor:[UIColor lightGrayColor]];    }else{//第二组的数据        //确定目前省所在的分组选择中的行数        NSLog(@"%d %d ",self.provincesIndex,row);        text =  [self.provincesList[self.provincesIndex] cities][row];        [label setBackgroundColor:[UIColor magentaColor]];    }    [label setText:text];    return label;}/** 设置选择的省份索引 */- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component{    if (component == 0) {        self.provincesIndex = row;        [pickerView reloadComponent:1];        //设置城市分组选择第一行        [pickerView selectRow:0 inComponent:1 animated:YES];    }}/**  设置分组宽度*/- (CGFloat) pickerView:(UIPickerView *)pickerView widthForComponent:(NSInteger)component{    if (component == 0) {        return 150;    }else{        return 100;    }}

这里写图片描述

这里写图片描述

总结

一、 Xcode快捷键
option+command+return-》显示助理窗口

二、Xcode7 添加PCH文件

1.) 打开你的Xcode工程. 在Supporting Files目录下,选择 File > New > File > iOS > Other > PCH File 然后点击下一步;
2.) 给你的PCH文件起名字TestDemo-Prefix.pch. 例如你的项目工程名为TestDemo然而你的PCH 文件的名字应该为 TestDemo-Prefix.pch,然后创建;
3)pch示例:
pch头文件 Expand source

4.) 找到 Project > Build Settings > 搜索 “Prefix Header“;
5.) “Apple LLVM 7.0 -Language″ 栏目中你将会看到 Prefix Header 关键字;
6.) 输入: YourProjectName/YourProject-Prefix.pch (如 TestDemo/TestDemo-Prefix.pch );
7.),将Precompile Prefix Header为YES,预编译后的pch文件会被缓存起来,可以提高编译速度。

8.) Clean 并且 build 你的项目.

三、 setApplicationIconBadgeNumber not having any effec

If you’re having trouble setApplicationIconBadgeNumber not working in iOS8+ it’s because you have to ask the user permission for local notifications starting in iOS8:

//解决设置提醒数字没效果的问题    UIUserNotificationType userNotificationTypes = UIUserNotificationTypeBadge;    UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:userNotificationTypes categories:nil];    [application registerUserNotificationSettings:settings];    //设置数字提醒    [application setApplicationIconBadgeNumber:10];

四、Xcode 7 创建 Empty Application 工程

从Xcode 6正式版开始就没有了 Empty Application 这个模板。 大部分创建 Empty Application 工程的方式一般为如下两种:
通过创建的 Single View Application 工程来自行修改。
通过将 Xcode 6 beta 中的模板复制过去。
这里讲解一下:通过创建的 Single View Application 工程来自行修改。
方法一、首先创建一个 Single View Application 工程
1、将 XX.storyboard 和 ViewController.H .M 文件进行delete
2、从Info.plist,将 Main storyboard file base name 一项删除;并在工程项目属性文件,将 Deployment Info 选项 中的 Main Interface 的内容设置为空。
3、在AppDelegate的didFinishLaunchingWithOptions:方法里面内返回之前添加代码,代码分为4部,分别是:

创建window 设置window背景 设置window的根控制器 设置可见

/** 创建window 设置window背景 设置window的根控制器 设置可见 */- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {    // Override point for customization after application launch.    self.window  = [[UIWindow alloc]initWithFrame:[[UIScreen mainScreen] bounds]];    [self.window setBackgroundColor:[UIColor whiteColor]];    //设置setRootViewController    [self.window setRootViewController:[[UIViewController alloc]init]];    //window要显示到屏幕,必须设置它为主窗口,并且设置为可见    [self.window makeKeyAndVisible];//Makes the receiver the key window and visible.    return YES;}

创建UIWindows,并设置主窗口且为可见 Expand source
p s: 应用尺寸就能根据屏幕大小进行调整了
1>打开工程项目属性文件,点击Target下面的第一项,再选择General选项卡,向下找到Use Asset Catalog按钮。点击它。
2>弹出对话框,点击Migrate即可。这样,应用尺寸就能根据屏幕大小进行调整了(Migrate launch images to an asset catalog)

启动页面的设置

appicon &LaunchImage

appIcon: 40*40 60*60 58*58 87*87 80*80 120*120 180*180

LaunchImage: RetinaHD5.5“ RetinaHD4.7“
**640 × 960 pixels、640 × 1136 pixels。

*如果不设置这两种的尺寸启动页的话,在4英寸、3.5英寸的设备上展示不了启动页,app 的高度也默认都是矮的960px.*** 

• 注意@3x 提供给开发的px 为1242*2208 ,但真实的px 是1080*1920,系统API会自动进行等比例缩小;

方法二:
复制 Empty Application.xctemplate 到目录{Xcode.app}/Contents/Developer/Platforms/iPhoneOS.platform/Developer/Library/Xcode/Templates/Project Templates/iOS/Application/ 中

原创粉丝点击