美文网首页iOS 学习历程
iOS 学习心得记录之:iOS启动函数main的个人见解

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

作者: 人话博客 | 来源:发表于2017-02-07 17:01 被阅读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列表里。

    相关文章

      网友评论

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

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