MST

星途 面试题库

面试题:Objective-C中weak与strong在内存管理上的区别

请详细阐述在Objective-C中,weak(弱引用)和strong(强引用)在内存管理方面有哪些不同?并举例说明在什么场景下适合使用weak,什么场景下适合使用strong。
15.7万 热度难度
编程语言Objective-C

知识考点

AI 面试

面试题答案

一键面试

1. weak(弱引用)和strong(强引用)在内存管理方面的不同

  • 引用计数影响
    • strong:当一个对象被strong指针指向时,对象的引用计数会增加。只要有至少一个strong指针指向该对象,该对象就不会被释放。例如:
NSObject *strongObject = [[NSObject alloc] init];
// 此时对象的引用计数至少为1
  • weakweak指针指向对象时,不会增加对象的引用计数。当对象的引用计数变为0并被释放时,指向它的所有weak指针会自动被设置为nil,从而避免野指针。例如:
NSObject *strongObject = [[NSObject alloc] init];
__weak NSObject *weakObject = strongObject;
strongObject = nil;
// 此时原来的对象引用计数为0,被释放,weakObject自动变为nil
  • 对象生命周期
    • strongstrong指针能够维持对象的生命周期,只要有strong指针存在,对象就不会被释放。这有助于确保对象在需要使用时一直可用。
    • weakweak指针不影响对象的生命周期,对象的释放与否取决于strong指针的情况。weak指针主要用于解决循环引用问题以及创建一种临时性的、不影响对象生命周期的引用。

2. 适合使用weak的场景

  • 解决循环引用:在视图控制器之间的父子关系或者视图之间的父子关系中,如果使用strong引用,很容易形成循环引用。例如,一个视图控制器ViewControllerA持有一个子视图SubView,而SubView又持有ViewControllerA,这就会导致循环引用。此时,在SubView中使用weak引用ViewControllerA可以解决这个问题。
// ViewControllerA.m
#import "ViewControllerA.h"
#import "SubView.h"

@interface ViewControllerA ()
@property (nonatomic, strong) SubView *subView;
@end

@implementation ViewControllerA
- (void)viewDidLoad {
    [super viewDidLoad];
    self.subView = [[SubView alloc] initWithFrame:self.view.bounds];
    self.subView.viewController = self;
    [self.view addSubview:self.subView];
}
@end

// SubView.h
#import <UIKit/UIKit.h>
#import "ViewControllerA.h"

@interface SubView : UIView
@property (nonatomic, weak) ViewControllerA *viewController;
@end

// SubView.m
#import "SubView.h"

@implementation SubView
@end
  • 监听者模式:当一个对象作为监听者,监听另一个对象的某些事件时,监听者对象对被监听对象使用weak引用。比如,Observer对象监听Observable对象的状态变化,Observer持有weak引用Observable,这样Observable的释放不会受到Observer的影响。

3. 适合使用strong的场景

  • 对象所有权明确:当一个对象对另一个对象拥有明确的所有权,并且需要确保该对象在其生命周期内一直存在时,使用strong引用。例如,一个Person类持有一个Car类的实例,PersonCar有所有权,在Person的生命周期内,Car应该一直存在。
@interface Car : NSObject
@end

@implementation Car
@end

@interface Person : NSObject
@property (nonatomic, strong) Car *car;
@end

@implementation Person
@end
  • 需要长期持有对象:在数据模型或者单例模式等场景下,对象需要被长期持有并在应用的不同部分使用,此时使用strong引用。例如,一个管理用户信息的单例类UserManager,应用的各个部分都可能需要访问该单例对象,所以使用strong引用确保其一直存在。
@interface UserManager : NSObject
+ (instancetype)sharedManager;
@end

@implementation UserManager
+ (instancetype)sharedManager {
    static UserManager *sharedManager = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        sharedManager = [[self alloc] init];
    });
    return sharedManager;
}
@end

在其他类中使用时:

@interface SomeClass : NSObject
@property (nonatomic, strong) UserManager *userManager;
@end

@implementation SomeClass
- (void)someMethod {
    self.userManager = [UserManager sharedManager];
}
@end