iOS 学习历程

iOS 学习心得记录之:iOS启动函数main的个人见解

2017-02-07  本文已影响149人  人话博客

首先启动main.m文件里的 main函数

int main(int argc, char * argv[]) {
    @autoreleasepool {
        return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
    }
}

说明一下:
1、UIApplicationMain()方法返回值是int类型。
方法签名:

  // If nil is specified for principalClassName, the value for NSPrincipalClass from the Info.plist is used. If there is no
  // NSPrincipalClass key specified, the UIApplication class is used. The delegate class will be instantiated using init.
  UIKIT_EXTERN int UIApplicationMain(int argc, char *argv[], NSString * __nullable principalClassName, NSString * __nullable delegateClassName);

2、函数有4个参数

1.argc 是启动参数,不用去管.

2.argv 是启动参数,不用去管.

3.nil 第三个参数传了nil,也就是方法签名里的 NSString *__nullable principalClassName.

principal adj. 主要的;资本的 n. 首长;校长;资本;当事人

对这个参数的注释是:if nil is specified for principalClassName,the value for NSPrincipalClass from info.plist is used.

如果,这个参数传递了nil,那么就会使用info.plist文件的配置信息。

于是就立马看了下项目里的plist,没有一个配置是对类型的描述的。所以不知道这个参数是干嘛使的。

//If there is no NSPrincipalClass key specified, the UIApplication class is used

接着的注释表达的意思,如果没有在info.plist里有对应的key是 NSprincipalClass ,就会默认使用 UIApplication 类型。

所以,第三个参数用的就是UIApplication class。

4.第四个参数的签名是:NSString * __nullable delegateClassName 看起来应该是一个委托类类型对象。

传递的参数是 [AppDelegate class] AppDelegate 的类对象。

第四个参数的注释是:the delegate class will be instantiated using init;
这个委托类型将会用于实例化。

instantiated v .实例化;具体化;实体化;

AppDelegate 类名后面有个 delegate 的后缀,这个类可能是满足了某个协议。

查看这个类的定义:

定义如下:

#import <UIKit/UIKit.h> //导入了UIKit 一看就知道是开发iPhone 设备的用的。ApplicationKit 用于开发MAC OS的。

【如果看到 #import ApplicationKit/ApplicationKit.h 就说明这个项目可能是开发MAC OS的。】

@interface AppDelegate : UIResponder <UIApplicationDelegate>
@property (strong,nonatomic) UIWindow *window;
@end

说明了3个问题:

1、AppDelegate 继承了 UIResponder类型。

2、AppDelegate 内部有一个默认的UIWindow类型的属性。(UIWindow : UIView : UIResponder)

3、最重要的一点,AppDelegate 实现了 UIApplicationDelegate 协议。

接着看看 UIApplicationDelegate 里定义了哪些方法。

- (void)applicationDidFinishLaunching:(UIApplication *)application;
- (BOOL)application:(UIApplication *)application willFinishLaunchingWithOptions:(nullable NSDictionary *)launchOptions NS_AVAILABLE_IOS(6_0);
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(nullable NSDictionary *)launchOptions NS_AVAILABLE_IOS(3_0);
- (void)applicationDidBecomeActive:(UIApplication *)application;
- (void)applicationWillResignActive:(UIApplication *)application;
- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url 

所以AppDelegate.m 文件里就实现了这些协议的方法了。

线索很零散,需要整理一下。

首先启动函数有4个参数,前2个不用管。后面接着的nil,会默认使用UIApplication类型,最后一个使用了AppDelegate类(实现了UIApplicationDelegate协议,内部还有一个默认的UIWindow属性);

这两个类型是如何分工的?

UIApplication 类是干嘛的?

AppDelegate 又是干嘛的?从协议方法来看,貌似是监控整个iOS程序声明周期的。那么UIAppliaction 又启到了什么作用呢?

答案呼之欲出了:UIApplication 表示了整个iOS程序。而AppDelegate 实现协议方法,提供UIApplication 生命周期中关键时刻的方法实现。

int main(int argc, char * argv[]) {
    @autoreleasepool {
        return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
    }
}

so:argc,argv who tm cares ?

nil = UIApplication 表示整个iOS程序本身

NSStringFromClass([AppDelegate class]) 实现协议方法,提供UIApplication 生命周期中关键时刻的方法实现。

ps:NSStrinFromClass([AppDelegate class]);是通过【类的class信息】,获取类名字符串的函数。所以第4个函数传递的是NSString * 类型。

证明:UIApplicationMain 函数的 第三个参数就是UIApplication,第四个参数就是AppDelegate.

这是一个没有改过main.m 启动函数的代码片段

int main(int argc, char * argv[]) {
    @autoreleasepool {
        
        return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
        
        //return UIApplicationMain(argc, argv, @"UIApplication", @"AppDelegate");
    }
}

这是程序启动界面:

Paste_Image.png

可以正常启动。

现在修改UIApplicationMain 函数代码参数为NSString * 常量。

Paste_Image.png

接着再次启动启动这个程序

Paste_Image.png

发现可以正常运行。于是就证明了之前的推断是正确的。

ps:什么是【类的class信息】?在iOS系统启动之后,所有的类都会以class的形式存放在代码区中。这个class的类类型包含了当前类名(className),当前类的属性列表(propertyList),方法列表(SELList),方法本身也是对象,以单个元素的形式存放在SELList列表里。

上一篇下一篇

猜你喜欢

热点阅读