IOS --runtime 学习笔记

本文详细介绍了Objective-C中的initialize和load方法。initialize在类接收第一条消息之前调用,常用于轻量级初始化,如设置静态变量。load方法在类或分类加载到运行时时调用,适合进行全局配置。文章通过代码示例展示了这两个方法的使用场景,并解释了它们的调用顺序和注意事项。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、 +(void)initialize

001 在接收到第一个消息之前初始化该类。

个人理解是该类内部发出第一条消息之前就会调用,那么第一条消息理解呢?alloc方法调用。

002 运行时initialize以线程安全的方式将消息发送给该类,提到线程安全 就会想到锁的作用,因为以线程安全方式发送消息,那么其他任何尝试给类发送消息的线程都会被阻塞,直到initialize执行完毕。

003 如果子类不实现initialize,则任何超类可以实现多次调用(运行时将调用继承的实现),或者子类显式调用[super initialize]。如果要保护自己免于多次运行,可以在

initialize 做一个过滤操作:

+ (void)initialize { if (self == [ClassName self]) { // ... do the initialization ... }}

004 initialize 方法限制为尽可能少的必要工作。因为在initialize方法中使用繁重的代码很有可能导致死锁。

例如在initialize方法中初始化静态变量

SDImageAWebPCoder类中

// These constants are available from iOS 14+ and Xcode 12. This raw value is used for toolchain and firmware compatibility

static NSString * kSDCGImagePropertyWebPDictionary = @"{WebP}";

static NSString * kSDCGImagePropertyWebPLoopCount = @"LoopCount";

static NSString * kSDCGImagePropertyWebPDelayTime = @"DelayTime";

static NSString * kSDCGImagePropertyWebPUnclampedDelayTime = @"UnclampedDelayTime";

 

@implementation SDImageAWebPCoder

 

+ (void)initialize {

#if __IPHONE_14_0 || __TVOS_14_0 || __MAC_11_0 || __WATCHOS_7_0

    // Xcode 12

    if (@available(iOS 14, tvOS 14, macOS 11, watchOS 7, *)) {

        // Use SDK instead of raw value

        kSDCGImagePropertyWebPDictionary = (__bridge NSString *)kCGImagePropertyWebPDictionary;

        kSDCGImagePropertyWebPLoopCount = (__bridge NSString *)kCGImagePropertyWebPLoopCount;

        kSDCGImagePropertyWebPDelayTime = (__bridge NSString *)kCGImagePropertyWebPDelayTime;

        kSDCGImagePropertyWebPUnclampedDelayTime = (__bridge NSString *)kCGImagePropertyWebPUnclampedDelayTime;

    }

#endif

}

例如在initialize方法中初始化监听某些通知

SDWebImageDownloader类中

+ (void)initialize {

    // Bind SDNetworkActivityIndicator if available (download it here: http://github.com/rs/SDNetworkActivityIndicator )

    // To use it, just add #import "SDNetworkActivityIndicator.h" in addition to the SDWebImage import

    if (NSClassFromString(@"SDNetworkActivityIndicator")) {

#pragma clang diagnostic push

#pragma clang diagnostic ignored "-Warc-performSelector-leaks"

        id activityIndicator = [NSClassFromString(@"SDNetworkActivityIndicator") performSelector:NSSelectorFromString(@"sharedActivityIndicator")];

#pragma clang diagnostic pop

        // Remove observer in case it was previously added.

        [[NSNotificationCenter defaultCenter] removeObserver:activityIndicator name:SDWebImageDownloadStartNotification object:nil];

        [[NSNotificationCenter defaultCenter] removeObserver:activityIndicator name:SDWebImageDownloadStopNotification object:nil];

 

        [[NSNotificationCenter defaultCenter] addObserver:activityIndicator

                                                 selector:NSSelectorFromString(@"startActivity")

                                                     name:SDWebImageDownloadStartNotification object:nil];

        [[NSNotificationCenter defaultCenter] addObserver:activityIndicator

                                                 selector:NSSelectorFromString(@"stopActivity")

                                                     name:SDWebImageDownloadStopNotification object:nil];

    }

}

005 initialize 每个类仅被调用一次

 

二 +(void)load

001 任何时候一个类或者分类被添加到runtime中就会被调用,实现这些类中专门的一些方法

 

002 initialization 执行步骤如下

1.所有初始化在任何你链接的库里

2. 所有load方法 在你的镜像中

3.所有C++初始化以及C++构造函数也在你的镜像中

4.所有初始化的库都链接到你

额外还有

一个类的的+load的方法在所有超类+load执行之后调用。

一个分类的+load的方法在类自身的+load执行之后调用。

在分类中可以实现方法混淆,如果多个分类中实现相同分类方法,调用依据来自于编译顺序

Person---->Student

Person---->Teacher

Person类中实现initialize

+(void)initialize{

    NSLog(@"Person initialize");

}

Student类中实现

+(void)initialize{

    NSLog(@"Student initialize");

}

- (void)viewDidLoad {

    [super viewDidLoad];

    Student *aSt = [[Student alloc] init];

    Teacher *aTcher = [[Teacher alloc] init];

}

先在父类Person 调用initialize 然后在Student中调用,Teacher 没有实现initialize只能父类Person 调用initialize

initialize 可以被多次调用

load先调用再调用initialize

2020-10-24 11:21:30.554789+0800 LearnLoadInitial[20451:1538690] Person load

2020-10-24 11:21:30.555318+0800 LearnLoadInitial[20451:1538690] Person+cat load

2020-10-24 11:21:30.601336+0800 LearnLoadInitial[20451:1538690] Person initialize

2020-10-24 11:21:30.601453+0800 LearnLoadInitial[20451:1538690] Person+cat personFun

 

 

 

 

 

 

 

 

 

参考文献:

https://developer.apple.com/documentation/objectivec/nsobject/1418815-load?language=objc

https://developer.apple.com/documentation/objectivec/nsobject/1418639-initialize?preferredLanguage=occ

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值