面试题答案
一键面试- 分析循环引用问题:
- 在这种情况下,
ClassA
持有ClassB
的引用,而ClassB
的NSArray
又持有多个ClassA
对象的引用,形成了循环引用。在MRC(Manual Reference Counting)模式下,如果不妥善处理,会导致内存泄漏。
- 在这种情况下,
- 解决方法:
- 打破循环引用的关键在于将其中一端的引用设置为非强引用。通常建议将
ClassB
中NSArray
对ClassA
对象的引用设置为非强引用(如assign
)。因为NSArray
本身通过引用计数来管理其内容,将对ClassA
的引用设置为非强引用可以避免循环引用。
- 打破循环引用的关键在于将其中一端的引用设置为非强引用。通常建议将
- 关键代码片段:
ClassA.h
:
#import <Foundation/Foundation.h>
@class ClassB;
@interface ClassA : NSObject
@property (nonatomic, strong) ClassB *classBProperty;
@end
ClassA.m
:
#import "ClassA.h"
#import "ClassB.h"
@implementation ClassA
- (void)dealloc {
NSLog(@"ClassA deallocated");
[super dealloc];
}
@end
ClassB.h
:
#import <Foundation/Foundation.h>
@class ClassA;
@interface ClassB : NSObject
@property (nonatomic, strong) NSArray *classAArray;
@end
ClassB.m
:
#import "ClassB.h"
#import "ClassA.h"
@implementation ClassB
- (void)dealloc {
NSLog(@"ClassB deallocated");
[super dealloc];
}
@end
- 使用示例:
#import <Foundation/Foundation.h>
#import "ClassA.h"
#import "ClassB.h"
int main(int argc, const char * argv[]) {
@autoreleasepool {
ClassA *a = [[ClassA alloc] init];
ClassB *b = [[ClassB alloc] init];
NSMutableArray *array = [NSMutableArray array];
[array addObject:a];
b.classAArray = array;
a.classBProperty = b;
[a release];
[b release];
}
return 0;
}
在这个示例中,ClassB
中的classAArray
对ClassA
对象是强引用,但如果不处理循环引用,对象无法正常释放。通过将ClassB
中对ClassA
的引用改为assign
类型(在MRC下手动管理引用计数时打破循环引用的一种方式),可以确保对象在不再被需要时能正确释放内存,避免内存泄漏。例如,可以修改ClassB.h
如下:
#import <Foundation/Foundation.h>
@class ClassA;
@interface ClassB : NSObject
@property (nonatomic, strong) NSMutableArray *classAArray;
@end
并在使用时,将添加到数组中的ClassA
对象设置为assign
类型的包装对象(这里简化示例未详细展示这部分复杂实现,实际可能需要自定义一个包含assign
类型ClassA
属性的类来包装),从而打破循环引用。
在dealloc
方法中打印日志是为了观察对象的释放情况。在实际代码中,要确保在对象生命周期结束时,通过release
方法正确减少对象的引用计数,以避免内存泄漏。