• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

iOSload和initialize

武飞扬头像
会飞的金鱼
帮助1

load和initialize详解

在介绍之前,我们首先来了解一下类的使用,我们要使用一个类,大概要经过以下步骤
1启动App,程序开始加载类到内存中(代码区) (void)load
2首次使用该类时,创建类对象(我们可以把它看作是一个单例,它在整个程序中只有一份) (void)initialize
3通过类对象创建实例对象 (instancetype)alloc、-(instancetype)init
4通过实例对象,我们就可使用实例方法、类属性了
从上面的步骤我们也大概了解到load和initialize的调用时机了,下面在来详细说一下

一、 load类方法

当类被引用进项目的时候就会执行load函数(在main函数开始执行之前),与这个类是否被用到无关,每个类的load函数只会自动调用一次.由于load函数是系统自动加载的,因此不需要再调用[super load],否则父类的load函数会多次执行。
●1.当父类和子类都实现load函数时,父类的load方法执行顺序要优先于子类
●2.当一个类未实现load方法时,不会调用父类load方法
●3.类中的load方法执行顺序要优先于类别(Category)
●4.当有多个类别(Category)都实现了load方法,这几个load方法都会执行,但执行顺序不确定(其执行顺序与类别在Compile Sources中出现的顺序一致)
●5.当然当有多个不同的类的时候,每个类load 执行顺序与其在Compile Sources出现的顺序一致

二、 initialize类方法

●即使类文件被引用进项目,但是没有使用,initialize不会被调用
●假如这个类放到代码中,而这段代码并没有被执行,这个函数是不会被执行的。
●类或者其子类的第一个方法被调用前调用
●由于是系统自动调用,也不需要再调用 [super initialize],否则父类的initialize会被多次执行
●父类的initialize方法会比子类先执行
●子类未实现initialize方法时,会调用父类initialize方法,子类实现initialize方法时,会覆盖父类initialize方法.
●当有多个Category都实现了initialize方法,会覆盖类中的方法,只执行一个(会执行Compile Sources 列表中最后一个Category 的initialize方法)

三、两者的异同
1、相同点
1load和initialize会被自动调用,不能手动调用它们。
2如果父类和子类都被调用,父类的调用一定在子类之前
3子类实现了load和initialize的话,会隐式调用父类的load和initialize方法。
4load和initialize方法内部使用了锁,因此它们是线程安全的。
2、不同点
1调用顺序不同,以main函数为分界, load方法在main函数之前执行, initialize在main函数之后执行。
2子类中没有实现 load方法的话,不会调用父类的 load方法;而子类如果没有实现 initialize方法的话,也会自动调用父类的 initialize方法。
3 load方法是在类被装在进来的时候就会调用, initialize在第一次给某个类发送消息时调用(比如实例化一个对象),并且只会调用一次,是懒加载模式,如果这个类一直没有使用,就不会调用到 initialize方法。
四、使用场景
1. load一般是用来交换方法Method Swizzle,由于它是线程安全的,而且一定会调用且只会调用一次,通常在使用UrlRouter的时候注册类的时候也在 load方法中注册。

 (void)load {

static dispatch_once_t oneToken;

dispatch_once(&oneToken, ^{

    Method imageNamed = class_getClassMethod(self,@selector(imageNamed:));

    Method mkeImageNamed =class_getClassMethod(self,@selector(swizze_imageNamed:));

    method_exchangeImplementations(imageNamed, mkeImageNamed);

    });

}

  (instancetype)swizze_imageNamed:(NSString*)name {

//这个时候swizze_imageNamed已经和imageNamed交换imp,所以当你在调用swizze_imageNamed时候其实就是调用imageNamed

UIImage * image;

if( IS_IPHONE ){

// iphone处理

UIImage * image = [self swizze_imageNamed:name];

    if (image != nil) {

        return image;

    } else {

        return nil;

    }

} else {

    // ipad处理,_ipad是自己定义,~ipad是系统自己自定义。

    UIImage *image = [self swizze_imageNamed:[NSString stringWithFormat:@"%@_ipad",name]];

    if (image != nil) {

            return image;

        }else {

            image = [self swizze_imageNamed:name];

            return image;

    }

}

2. initialize方法主要用来对一些不方便在编译期初始化的对象进行赋值,或者说对一些静态常量进行初始化操作。


/ In Person.m

// int类型可以在编译期赋值

static int someNumber = 0;

static NSMutableArray *someArray;

  (void)initialize {

if (self == [Person class]) {

    // 不方便编译期复制的对象在这里赋值

    someArray = [[NSMutableArray alloc] init];

    }

}

五、总结
1load和initialize方法都会在实例化对象之前调用
2load执行在main函数以前,initialize执行main函数之后
3这两个方法会被自动调用,不能手动调用它们。
4load和initialize方法都不用显示的调用父类的方法而是自动调用
5子类没有initialize方法也会调用父类的方法,而load方法则不会调用父类
6initialize方法对一个类而言只会调用一次(Person、或者是Person Category)都是一个Perosn类。load方法则是每个都会调用,只要你写了load方法,添加到工程都会实现。
7load方法通常用来进行Method Swizzle,initialize方法一般用于初始化全局变量或静态变量。
8load和initialize方法内部使用了锁,因此它们是线程安全的。实现时要尽可能保持简单,避免阻塞线程,不要再使用锁。

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanhgaibfb
系列文章
更多 icon
同类精品
更多 icon
继续加载