面试题答案
一键面试1. 定义属性
首先在类的接口部分定义需要自定义存取方法的属性。假设我们有一个NSString
类型的属性customString
:
@interface MyClass : NSObject
@property (nonatomic, strong) NSString *customString;
@end
这里使用nonatomic
表示非原子性访问,strong
表明该属性对对象具有强引用。
2. 编写自定义的getter方法
在类的实现部分编写getter方法。getter方法的作用是返回属性的值。
@implementation MyClass
- (NSString *)customString {
return _customString;
}
@end
这里直接返回实例变量_customString
。在ARC(自动引用计数)环境下,不需要手动管理对象的引用计数,ARC会自动处理对象的持有和释放。
3. 编写自定义的setter方法
编写setter方法来设置属性的值,并处理内存管理。
@implementation MyClass
- (void)setCustomString:(NSString *)newString {
if (_customString != newString) {
[_customString release];
_customString = [newString retain];
}
}
@end
在MRC(手动引用计数)环境下:
- 首先检查新值和旧值是否相同,如果不同才进行处理。
- 释放旧的
_customString
对象(调用release
方法,减少其引用计数)。 - 对新的
newString
对象调用retain
方法,增加其引用计数,然后赋值给_customString
。
在ARC环境下,setter方法如下:
@implementation MyClass
- (void)setCustomString:(NSString *)newString {
if (_customString != newString) {
_customString = newString;
}
}
@end
ARC会自动处理对象的引用计数,开发者无需手动调用retain
、release
等方法。
4. 与默认合成存取方法在内存管理上的差异
- MRC环境:
- 默认合成存取方法:编译器会自动生成符合内存管理规则的存取方法。对于
strong
属性,setter方法会先对旧值调用release
,再对新值调用retain
。getter方法会直接返回实例变量。 - 自定义存取方法:开发者需要手动编写内存管理代码,如上述setter方法中的
release
和retain
操作,以确保内存管理正确。如果编写错误,很容易导致内存泄漏或悬空指针等问题。
- 默认合成存取方法:编译器会自动生成符合内存管理规则的存取方法。对于
- ARC环境:
- 默认合成存取方法:ARC会自动管理对象的引用计数,编译器生成的存取方法会按照ARC规则处理对象的持有和释放。
- 自定义存取方法:开发者无需手动管理引用计数,但需要确保自定义的存取方法逻辑不破坏ARC的内存管理机制。例如,在ARC环境下,不能手动调用
retain
、release
、autorelease
等方法。如果在自定义存取方法中进行了错误的内存操作(如手动释放对象),会导致编译错误或运行时异常。