iOS中load方法和分类方法加载和调用顺序

在iOS开发中,我们经常会使用load方法和分类方法来实现一些功能扩展和初始化操作。load方法是在类被加载到内存时自动调用的方法,而分类方法则是为已有的类添加新的方法。本文将详细介绍load方法和分类方法的加载和调用顺序,并通过代码示例来说明。

load方法的加载和调用顺序

在Objective-C中,每个类都有一个load方法,这个方法是在类被加载到内存时自动调用的。load方法的定义如下:

+ (void)load {
    // 在这里添加需要执行的代码
}

load方法是在程序运行时自动调用的,由系统负责调用,我们无需手动调用。load方法的调用顺序遵循如下规则:

  1. 先调用父类的load方法,再调用子类的load方法;
  2. 先调用类的load方法,再调用分类的load方法;
  3. 调用顺序是根据类在编译时的顺序来确定的。

下面是一个示例,演示了load方法的加载和调用顺序:

// MyClass.h
@interface MyClass : NSObject
@end

// MyClass.m
#import "MyClass.h"

@implementation MyClass

+ (void)load {
    NSLog(@"MyClass load");
}

@end

// MySubClass.h
@interface MySubClass : MyClass
@end

// MySubClass.m
#import "MySubClass.h"

@implementation MySubClass

+ (void)load {
    NSLog(@"MySubClass load");
}

@end

上述代码中,MySubClass继承自MyClass,我们可以通过运行下述代码来观察load方法的调用顺序:

int main(int argc, char * argv[]) {
    @autoreleasepool {
        NSLog(@"Before MyClass and MySubClass are loaded");
        [MySubClass class];
        NSLog(@"After MyClass and MySubClass are loaded");
    }
    return 0;
}

输出结果如下:

Before MyClass and MySubClass are loaded
MyClass load
MySubClass load
After MyClass and MySubClass are loaded

从输出结果可以看出,首先调用了MyClass的load方法,然后调用了MySubClass的load方法。

分类方法的加载和调用顺序

分类方法是用来为已有的类添加新的方法的。分类方法的定义如下:

@interface ClassName (CategoryName)
// 添加新的方法
@end

分类方法的加载和调用顺序如下:

  1. 如果有多个分类为同一个类添加了相同的方法,那么只会调用最后编译的分类中的方法;
  2. 如果有多个分类为同一个类添加了不同的方法,那么每个分类中的方法都会被调用;
  3. 如果有多个分类为同一个类添加了相同的属性,那么只有最后编译的分类中的属性会生效。

下面是一个示例,演示了分类方法的加载和调用顺序:

// MyClass.h
@interface MyClass : NSObject
@end

// MyClass.m
#import "MyClass.h"

@implementation MyClass

- (void)sayHello {
    NSLog(@"Hello from MyClass");
}

@end

// MyClass+Category1.h
@interface MyClass (Category1)
@end

// MyClass+Category1.m
#import "MyClass+Category1.h"

@implementation MyClass (Category1)

- (void)sayHello {
    NSLog(@"Hello from Category1");
}

@end

// MyClass+Category2.h
@interface MyClass (Category2)
@end

// MyClass+Category2.m
#import "MyClass+Category2.h"

@implementation MyClass (Category2)

- (void)sayHello {
    NSLog(@"Hello from Category2");
}

@end

上述代码中,我们为MyClass类分别添加了Category1和Category2两个分类,它们都重写了sayHello方法。下面是一个使用这些分类的示例:

int main(int argc, char * argv[]) {
    @autoreleasepool {
        MyClass *myClass = [[MyClass alloc] init];
        [myClass sayHello];
    }
    return 0;
}

输出结果如下:

Hello from Category2

从输出结果可以看出,最后编译的分类Category2中的sayHello方法被调用。如果我们将Category2的内容注释掉,再次运行代码,输出结果为:

Hello from Category1
``