iOS开发基础23-iOS开发中的Info.plist、UIApplication及其Delegate、UIWindow详解

在iOS开发中,有一些系统文件和类是我们经常会接触并且必须熟悉的。这些包括Info.plistUIApplication类及其代理,以及UIWindow

一、Info.plist常见设置

1. 什么是Info.plist

在每一个iOS项目中,都会有一个名为"工程名-Info.plist"的文件,这个文件位于Supporting Files文件夹下。Info.plist(全称Information Property List)用于对工程进行一些运行时的配置,比如应用程序的标识符、版本号、图标等。这个文件非常重要,不能删除。

  • 在旧版本的Xcode中,项目的配置文件名为"Info.plist"
  • 请注意,项目中的其他Plist文件不能带有"Info"这个字眼,以免被误认为是主配置文件Info.plist
  • InfoPlist.strings文件与Info.plist文件有关联,用于本地化。

2. 常见属性(以文本编辑器打开时的键名表示)

属性 Key 描述
Localiztion native development region CFBundleDevelopmentRegion 本地化相关属性
Bundle display name CFBundleDisplayName 应用安装后显示的名称,限制在10-12个字符,超出将会被缩写
Icon file CFBundleIconFile 应用程序图标名称,通常为Icon.png
Bundle version CFBundleVersion 应用程序的版本号,每次发布新版本到App Store时需要递增
Main storyboard file base name NSMainStoryboardFile 主storyboard文件的名称
Bundle identifier CFBundleIdentifier 项目的唯一标识,部署到真机时需要

3. PCH文件

PCH(Precompiled Header)文件是一个提前编译好的头文件,用于存放一些公用的宏定义和头文件。它会在编译时自动被引入到每个源文件中。在Xcode中可以通过项目的Build Settings找到Prefix Header设置来指定PCH文件。

// 在PCH文件中
#ifdef __OBJC__
#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>

// 自定义Log,适用于Debug模式,发布时不输出
#ifdef DEBUG
#define XMGLog(...) NSLog(__VA_ARGS__)
#else
#define XMGLog(...)
#endif

// 定义一个判断iOS版本的宏
#define iOS8 ([[UIDevice currentDevice].systemVersion floatValue] >= 8.0)

#endif

二、UIApplication

1. 什么是UIApplication

UIApplication对象是应用程序的象征,每个iOS应用都有且只有一个UIApplication实例,可以通过[UIApplication sharedApplication]获取。应用程序启动后创建的第一个对象就是UIApplication对象。

UIApplication对象主要用于进行一些应用级别的操作。

2. 常用属性和方法

常用属性

  • applicationIconBadgeNumber:设置应用程序图标右上角的红色提醒数字。

    [UIApplication sharedApplication].applicationIconBadgeNumber = 10;
    
  • networkActivityIndicatorVisible:设置联网指示器的可见性。

    [UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
    

UIApplication管理状态栏

从iOS 7开始,状态栏的管理提供了两种方式:通过UIViewController管理和通过UIApplication管理。

通过UIViewController管理
  • 状态栏的样式

    - (UIStatusBarStyle)preferredStatusBarStyle {
        return UIStatusBarStyleLightContent;
    }
    
  • 状态栏的可见性

    - (BOOL)prefersStatusBarHidden {
        return NO;
    }
    
通过UIApplication管理

如果你想通过UIApplication来管理状态栏,需要在Info.plist中进行设置,并实现相关方法。

使用UIApplication的openURL:方法

openURL:方法是一个非常强大的功能,可以用来执行多种操作:

// 打电话
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"tel://10086"]];

// 发短信
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"sms://10086"]];

// 发邮件
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"mailto://12345@qq.com"]];

// 打开一个网页
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"http://www.baidu.com"]];

3. UIApplication单例模式

单例模式是指一个类只能存在一个实例。UIApplication就是通过单例模式实现的。

// 获取应用程序的象征
UIApplication *app = [UIApplication sharedApplication];

下面是模仿苹果内部原理写的一个单例对象:

#import <Foundation/Foundation.h>

@interface Person : NSObject
+ (instancetype)sharedPerson;
@end


#import "Person.h"
@implementation Person

static Person *p = nil;

+ (void)load {
    // 应用启动时创建单例实例
    [self sharedPerson];
}

+ (instancetype)sharedPerson {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        NSLog(@"dispatch_once");
       p = [[self alloc] init];
    });
    return p;
}

+ (instancetype)alloc {
    if (p) {
        NSException *exce = [NSException exceptionWithName:@"NSInternalInconsistencyException" reason:@"There can only be one Person instance." userInfo:nil];
        [exce raise];
    }
    return [super alloc];
}
@end

三、UIApplication及其Delegate

1. 应用程序的生命周期和系统事件

iOS应用程序会经常受到各种干扰,例如来电、锁屏等。这些系统事件发生时,UIApplication会通知其代理(delegate)对象,由delegate来处理这些事件。

常见的事件包括:

  • 应用程序的生命周期事件(如启动和关闭)
  • 系统事件(如来电)
  • 内存警告

2. UIApplicationDelegate协议

UIApplicationDelegate协议定义了一些用于处理应用程序状态和系统事件的方法,例如:

// 应用接收到内存警告时调用
- (void)applicationDidReceiveMemoryWarning:(UIApplication *)application;

// 应用进入后台时调用(比如按了home键)
- (void)applicationDidEnterBackground:(UIApplication *)application;

// 应用启动完毕时调用
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions;

3. AppDelegate

每次新建项目时,都会自动创建一个带有“AppDelegate”字眼的类,它就是UIApplication的代理。该类默认已经遵守了UIApplicationDelegate协议,并实现了相关的生命周期方法。例如:

#import "AppDelegate.h"

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    // 应用启动后的初始化代码
    return YES;
}

- (void)applicationDidEnterBackground:(UIApplication *)application {
    // 应用进入后台时执行的代码
}

- (void)applicationDidReceiveMemoryWarning:(UIApplication *)application {
    // 应用接收到内存警告时执行的代码
}

@end

四、UIWindow

1. 什么是UIWindow

UIWindowUIView的子类,通常在一个应用程序中至少会有一个UIWindow。应用程序启动时,首先会创建一个UIWindow,然后再创建视图控制器的view,最后将视图添加到UIWindow上,使之显示在屏幕上。

2. 添加UIView到UIWindow的方式

可以通过以下两种常见方式将UIView添加到UIWindow中:

  1. 直接将UIView添加到UIWindow中,但不会理会UIView对应的UIViewController

    [window addSubview:yourView];
    
  2. 使用rootViewController属性设置根视图控制器,该视图控制器的view会自动添加到UIWindow中,并管理其生命周期。

    window.rootViewController = yourViewController;
    

3. UIWindow常用方法

  • makeKeyWindow:将当前UIWindow变为主窗口(keyWindow)。
  • makeKeyAndVisible:将当前UIWindow变为主窗口并显示出来。

4. 获取UIWindow

  • 获取应用程序中所有打开的UIWindow列表:

    NSArray *windows = [UIApplication sharedApplication].windows;
    
  • 获取当前应用程序的主窗口:

    UIWindow *keyWindow = [UIApplication sharedApplication].keyWindow;
    
  • 获取某个UIView所在的UIWindow

    UIWindow *viewWindow = yourView.window;
    

五、iOS程序的启动过程

应用程序启动时,main函数调用UIApplicationMain函数:

int UIApplicationMain(int argc, char *argv[], NSString *principalClassName, NSString *delegateClassName);

参数解释:

  • argcargv:传递给UIApplicationMain进行相关处理即可。
  • principalClassName:指定应用程序类名,通常为UIApplication或其子类;如果为nil,则用UIApplication类作为默认值。
  • delegateClassName:指定应用程序的代理类,该类必须遵守UIApplicationDelegate协议。

UIApplicationMain函数会创建UIApplication对象和其delegate,设置run loop进行事件处理。程序启动后会首先调用delegate的application:didFinishLaunchingWithOptions:方法。

六、四大对象的关系

  • UIApplication:代表整个应用程序,是单例模式,负责应用级别的操作。
  • UIApplicationDelegate:处理应用程序的生命周期事件和系统事件。
  • UIWindow:是UIView的子类,显示和管理应用程序的内容。
  • UIViewController:负责管理视图和处理用户交互。

它们之间的关系可以简单描述为:

  • UIApplication通过UIApplicationDelegate管理应用的生命周期。
  • 应用启动时,创建UIWindow,然后设置rootViewController,将视图控制器的view添加到UIWindow上。
posted @ 2015-07-27 23:57  Mr.陳  阅读(431)  评论(0编辑  收藏  举报