Apple Documentation --Objective-C系列

方法名:initialize

声明

+ (void)initialize;

讨论

在这个类或集成与这个类的子类第一次被加载前,runtime 会发送initialize消息来调用这个方法。initialize消息是这个类从runtime中收到的第一个消息,父类接收到这个消息在子类之前。

runtime是以线程安全方式向类发送initialize消息,而且对这个类发送的第一个消息就是initialize消息,其他的线程如果尝试发送消息给这个类将会阻塞知道initialize完成。

如果子类没有实现initialize,父类的initialize也许会多次被调用。runtime会根据继承关系来调用或者子类明确的指出调用[super initialize]。如果你想自己去管理或者控制这种多次调用,你可以在下方注释的地方进行实现:

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

因为initialize是以阻塞方式被调用的,所以在这个方法中应尽可能减少代码工作量,然后由于是阻塞方式调用所以任何调用其他类的代码都可能导致死锁。所以不要在initialize中进行复杂的逻辑,尽量简化。

特别注意

initialize每个类只调用一次,如果你想对类和类的类别个字单独进行初始化,你应该实现load方法。

方法名:load

当类或者类别被加入到runtime的时候进行调用,一般用于在类被加载前实现一些特殊的操作

声明

+ (void)load;

讨论

load消息在动态加载和静态链接的时候都会被发送,但仅仅这个类或者类别实现这个方法的时候才会有相应

初始化顺序如下:

  1. 调用所有的Framework中的初始化方法
  2. 调用所有的+load方法
  3. 调用C++的静态初始化方法及C/C++中的attribute(constructor)函数
  4. 调用所有链接到目标文件的framework中的初始化方法

此外:

  • 一个类的+load方法在其父类的+load方法后调用
  • 一个Category的+load方法在被其扩展的类的自有+load方法后调用

+load方法中,可以安全地向其它无关的类发送消息,但接收消息的类中的+load方法可能尚未实现。

方法名:init

子类用来初始化一个新的对象,并立刻给该对象分配内存

声明

- (instancetype)init;

返回值

一个初始化的对象,如果因为某种原因没有创建成果那么就会返回nil,这样就不会抛出异常。

讨论

一个init消息一定会与alloc(或者allocWithZone:)消息出现在同一行代码中:

SomeClass *object = [[SomeClass alloc] init];

一个对象只有被初始化了才能被使用。

在一般情况下,你必须调用父类初始化方法来初始化并返回一个对象,如果不能初始化的话,就会返回nil。举例,假设有一个类——BuiltInCamera类,这个类当运行的设备中没有摄像头的时候进行初始化会返回nil

- (instancetype)init {
    if (self = [super init]) {
        // Initialize self
    }
    return self;
}

在一般情况下,你都要通过init来获取返回对象,而不是通过alloc或者allocWithZone:


initialize,load,init 代码示例

创建一个person类,并在其.m文件中实现以下三个方法

//
//  Person.m
//  AFNetworingSourceTest
//
//  Created by Mac on 2018/7/12.
//  Copyright © 2018年 MJJ. All rights reserved.
//

#import "Person.h"

@implementation Person

+(void)initialize {
    NSLog(@"%s", __FUNCTION__);
}

-(instancetype)init {
    NSLog(@"%s", __FUNCTION__);
    return  self;
}

+(void)load {
    NSLog(@"%s", __FUNCTION__);
}
@end

然后在viewDidLoad中初始化两个实例

- (void)viewDidLoad {
    [super viewDidLoad];
    Person* person1  = [[Person alloc]init];
    Person* person2  = [[Person alloc]init];
    // Do any additional setup after loading the view, typically from a nib.
}

控制台打印:

2018-07-12 12:34:19.095313+0800 AFNetworingSourceTest[62407:43110238] +[Person load]
2018-07-12 12:15:31.053588+0800 AFNetworingSourceTest[61566:43077247] +[Person initialize]
2018-07-12 12:15:31.053690+0800 AFNetworingSourceTest[61566:43077247] -[Person init]
2018-07-12 12:15:31.053787+0800 AFNetworingSourceTest[61566:43077247] -[Person init]

可以看到尽管创建了2个实例,但是initialize只调用了一次,而且是在创建的时候被调用,然后init调用了两次

接下来给Person创建一个子类Man

#import "Person.h"

@interface Man : Person

@end

#import "Man.h"

@implementation Man

@end

修改Personinitialize方法打印类名

+(void)initialize {
    NSLog(@"%s %@", __FUNCTION__,[self class]);
}

控制台打印:

2018-07-12 12:31:47.690548+0800 AFNetworingSourceTest[62342:43103509] +[Person load]
2018-07-12 12:31:49.123319+0800 AFNetworingSourceTest[62342:43103509] +[Person initialize] Person
2018-07-12 12:31:49.123443+0800 AFNetworingSourceTest[62342:43103509] -[Person init]
2018-07-12 12:31:49.123572+0800 AFNetworingSourceTest[62342:43103509] -[Person init]
2018-07-12 12:31:49.123665+0800 AFNetworingSourceTest[62342:43103509] +[Person initialize] Man
2018-07-12 12:31:49.123740+0800 AFNetworingSourceTest[62342:43103509] -[Person init]

initialize方法输出了两次,一个子类没有实现initialize方法,那么父类会调用这个方法两次,一次为自己,另一次为子类。load方法在initialize之前调用


方法名:alloc

给对应的类返回一个新的实例

声明

+ (instancetype)alloc;

返回值

一个新的实例

讨论

这个新的实例的isa指针被初始化为一个数据结构体用来描述该类;其他实例变量的内存被设置为0.

你必须使用init方法来完成初始化过程。
举例:

TheClass *newObject = [[TheClass alloc] init];

初始化不要重写alloc,而应该根据每个类来实现其自身的init方法。

因为历史原因,alloc会唤起allocWithZone:方法

方法名:allocWithZone

给对应的类返回一个新的实例

声明

+ (instancetype)allocWithZone:(struct _NSZone *)zone;

参数

zone 这个参数已被忽略,传nil即可

返回值

一个新的实例

讨论

这个新的实例的isa指针被初始化为一个数据结构体用来描述该类;其他实例变量的内存被设置为0.

你必须使用init方法来完成初始化过程。
举例:

TheClass *newObject = [[TheClass allocWithZone:nil] init];

初始化不要重写alloc,而应该根据每个类来实现其自身的init方法。

这个方法没用了,没啥好看的

方法名:copy

返回一个从从copyWithZone:获取的对象

声明

- (id)copy;

返回值

返回的对象是从NSCopying协议的copyWithZone:方法中获取

讨论

使用NSCoping协议可以很方便的为一个类添加copy方法,当然,一定要实现copyWithZone:方法,不然会抛出一个异常。
继承于NSObject的类自身不提供NSCopying协议,子类必须对这个协议添加支持,并且实现copyWithZone:方法
子类的copyWithZone:调用顺序:这个方法会首先向父类发送消息,并将其实现,除非这个子类是直接从NSObject派生

方法名:copyWithZone

返回一个接收者(对象)

声明

+ (id)copyWithZone:(struct _NSZone *)zone;

参数

zone
不用管这个参数,直接可以忽略

返回值

一个对象

讨论

当你需要一个可以实现NSCopying协议的类时需要用到这个方法,要实现这个方法.例如,该方法允许您使用类对象作为NSDictionary对象的键,不用重写这个方法

方法名:mutableCopy

mutableCopyWithZone 返回一个对象,zone参数为nil

声明

- (id)mutableCopy;

返回值

返回的对象是由NSMutableCopying协议方法mutableCopyWithZone:返回,zone参数为nil

讨论

对于采用NSMutableCopying协议的类来说,这是一种方便的方法。如果mutableCopyWithZone没有实现,则会引发异常。

方法名:mutableCopyWithZone:

返回一个对象

声明

zone:用于创建内存区域

讨论

类对象可以使用这个方法来使自身符合NSMutableCopying协议,例如,该方法允许您使用类对象作为NSDictionary对象的键,不用重写这个方法

方法名:dealloc

释放对象占用的内存

声明

- (void)dealloc;

讨论

如果在该对象内存被释放时候再次发送消息给该对象就会生成一个错误,可以重写这个方法来释放实例变量之外的对象的内存释放,例:

- (void)dealloc {
    free(myBigBlockOfMemory);
}

delloc的实现中,不要调用超类的实现。你应该尽量避勉使用 dealloc 管理有限资源诸如文件描述符的生命周期。决不要直接发送 dealloc 消息。相反,任何对象的 dealloc 方法由运行时调用。参看 高级内存管理编程指南 以获得更详细的内容。

特别注意事项

当未使用 ARC 时,你的 dealloc 实现必须把调用父类的实现作为最后一条指令。(隐含的意思就是,使用 ARC 时不能调用父类的实现)

方法名:new

分配给接收类一个新实例,向它发送一个init消息,并返回初始化的对象。

声明

+ (instancetype)new;

返回值

一个接收类的新的实例

讨论

该方法是alloc和init的组合。与alloc一样,它初始化新对象的isa实例变量,以便指向类数据结构。然后调用init方法来完成初始化过程。

方法名:class

返回一个类对象

声明

+ (Class)class;

返回值

一个类对象

讨论

当一个类是消息接受者是可以通过它的名称来引用它。在其他所有情况下,类对象必须通过此方法或者类似方法获得。例如,这里将SomeClass作为一个参数餐递给isKindOfClass:方法(在NSObject协议中声明):

BOOL test = [self isKindOfClass:[SomeClass class]];
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,948评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,371评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,490评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,521评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,627评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,842评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,997评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,741评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,203评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,534评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,673评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,339评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,955评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,770评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,000评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,394评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,562评论 2 349

推荐阅读更多精彩内容