- 以下代码运行会存在什么问题:
@autoreleasepool {
for (int i = 0; i < INT_MAX; i++) {
SFPerson *person = [[SFPerson alloc] init];
[person autorelease];
}
}
在 MRC 环境中,调用方法 autorelease 虽然会让 person 实例引用计数减 1,但不是立即减 1。其本质上只是把对象放到离它最近的自动释放池里,当自动释放池销毁了,才会向自动释放池里的每一个对象发送 release 消息。这道题问题就出在 autorelease 上,因为 INT_MAX 是一个很大的整型数,而 autorelease 又不能使引用计数立即减 1,所以在循环结束前会造成内存溢出的问题。
解决方案也很简单,做如下更改,就能保证在每创建一个对象,就会得到及时释放。
@autoreleasepool {
for (int i = 0; i < INT_MAX; i++) {
@autoreleasepool {
SFPerson *person = [[SFPerson alloc] init];
[person autorelease];
}
}
}
- 以下代码运行会存在什么问题:
@autoreleasepool {
NSString *string = [[NSString alloc] init]; // 1
[string retain]; // 2
[string retain]; // 3
string = @"aaa";
[string release];
[string release];
[string release];
}
指针变量 string 原本指向一块开辟的堆区空间,但经过重新给赋值后,string 的指向发生了变化,指向常量区。常量区的变量是自动管理内存的,不需要我们手动释放,这样一来,就导致原来的堆区内存没有被释放,造成内存泄露。
- 请写出
NSLog方法打印的内容,并作出解释:
// .h 文件
#import "SFPerson.h"
@interface SFStudent : SFPerson
@end
// .m 文件
#import "SFStudent.h"
@implementation SFStudent
- (instancetype)init {
self = [super init];
if (self) {
NSLog(@"%@", NSStringFromClass([self class]));
NSLog(@"%@", NSStringFromClass([super class]));
}
return self;
}
@end
输出结果:都输出 SFStudent
解释:self 是类的隐藏参数,指向当前调用方法的这个类的实例,而 super 关键字只是一个编译器标志符,和self 是指向同一个消息接收者的。上述例子中,不管调用那个,接收消息的对象都是 SFStudent *xx 这个对象。而不同的是,super 是告诉编译器,调用 class 这个方法时要去父类的方法开始查找,而不是从本类开始查找。self 则会从当前类的方法列表中开始查找,如果没找到,再去父类中查找;而当使用 super 时,则从父类的方法开始查找,然后调用父类的这个方法。
其中方法 class 默认实现如下,具体可以去苹果开源的源码中加以验证:
- Class)class {
return object_getClass(self);
}
我们梳理一下调用流程来加深理解:
- 调用
[self class]时,系统先调用objc_msgSend函数,第一个参数是SFStudent当前这个实例,然后在SFStudent这个类中查找(Class)class这个方法,发现自身没有实现,再去父类SFPerson里面去找,也没有找到具体实现,最后在基类NSObject中发现这个方法。而这个方法的实现就是返回self的类别,因此输出 SFStudent; - 调用
[super class]时,系统会去调用objc_msgSendSuper函数。第一步先构造objc_super结构体,结构体的第一个成员是self,第二个成员是(id)class_getSuperclass(objc_getClass(@"SFPerson"));实际结果会输出 SFPerson。第二步是去SFPerson这个类中去找(Class)class这个方法,结果没有,然后去基类NSObject找到了。最后内部是使用objc_msgSend(objc_super->receiver,@selector(class))去调用,此时已经和[self class]调用相同了,最后的输出结果是相同的,都是SFStudent。