MST

星途 面试题库

面试题:如何自定义Objective-C属性的存取方法并处理内存管理

假设你有一个自定义的Objective-C类,其中有一个属性需要自定义其存取方法,并且该属性涉及到对象的内存管理(例如,属性是一个对象类型,需要考虑引用计数等内存问题)。请详细描述实现步骤,包括如何编写自定义的getter和setter方法,以及在其中如何正确处理内存管理,同时说明与使用默认合成存取方法在内存管理上的差异。
21.0万 热度难度
编程语言Objective-C

知识考点

AI 面试

面试题答案

一键面试

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会自动处理对象的引用计数,开发者无需手动调用retainrelease等方法。

4. 与默认合成存取方法在内存管理上的差异

  • MRC环境
    • 默认合成存取方法:编译器会自动生成符合内存管理规则的存取方法。对于strong属性,setter方法会先对旧值调用release,再对新值调用retain。getter方法会直接返回实例变量。
    • 自定义存取方法:开发者需要手动编写内存管理代码,如上述setter方法中的releaseretain操作,以确保内存管理正确。如果编写错误,很容易导致内存泄漏或悬空指针等问题。
  • ARC环境
    • 默认合成存取方法:ARC会自动管理对象的引用计数,编译器生成的存取方法会按照ARC规则处理对象的持有和释放。
    • 自定义存取方法:开发者无需手动管理引用计数,但需要确保自定义的存取方法逻辑不破坏ARC的内存管理机制。例如,在ARC环境下,不能手动调用retainreleaseautorelease等方法。如果在自定义存取方法中进行了错误的内存操作(如手动释放对象),会导致编译错误或运行时异常。