我对Xcode中使用Obj-C的强引用和弱引用感到困惑。 当我创建两个内部相互交叉引用的对象时,所有弱点:
Mouse *mouse = [[Mouse alloc] initWithComputer:nil];
Computer *computer = [[Computer alloc] initWithMouse:mouse];
NSLog(@"%@", computer.mouse); //prints legit address
mouse = nil; //destroy the ONLY strong reference to Mouse
NSLog(@"%@", computer.mouse); //still prints(holds) the same legit address
在 mouse = nil;
之前mouse = nil;
之后"摧毁"对于鼠标类鼠标的唯一强引用,鼠标 computer.mouse 的实例在应该释放时仍保留相同的内存地址。
只有Xcode中的SWIFT中的相同代码才能正常工作并释放 computer.mouse 所占用的内存,使其 nil
我的Obj-c代码有什么问题吗?我的Xcode是最新的,虽然在之前的版本中,我在Obj-c中也没有运气。我将不胜感激任何帮助。
以下是我的课程:
Computer.h
#import <Foundation/Foundation.h>
@class Mouse;
@interface Computer : NSObject
@property (nonatomic, weak) Mouse *mouse;
- (instancetype) initWithMouse: (Mouse *) userPutMouse ;
@end
Computer.m
#import "Computer.h"
#import "Mouse.h"
@implementation Computer
- (instancetype) initWithMouse: (Mouse *) userPutMouse {
self = [super init];
if (self) {
self.mouse = userPutMouse;
self.mouse.computer = self;
}
return self;
}
@end
Mouse.h
#import <Foundation/Foundation.h>
@class Computer;
@interface Mouse : NSObject
@property (nonatomic, weak) Computer *computer;
- (instancetype) initWithComputer: (Computer *) userPutComputer;
@end
Mouse.m
#import "Mouse.h"
#import "Computer.h"
@implementation Mouse
- (instancetype) initWithComputer: (Computer *) userPutComputer {
self = [super init];
if (self ) {
if (userPutComputer) {
self.computer = userPutComputer;
}
}
return self;
}
@end
答案 0 :(得分:4)
自动合成的getter将他们返回的对象放入自动释放池中。因此,您将mouse
分配给nil
并不会终止最终的拥有参考。永远不要假设您是唯一拥有任何引用的人,只能确保您遵循适当的行为。
对于经验证明,试试这个:
Mouse *mouse;
Computer *computer;
@autoreleasepool {
mouse = [[Mouse alloc] initWithComputer:nil];
computer = [[Computer alloc] initWithMouse:mouse];
NSLog(@"%@", computer.mouse); //prints legit address
mouse = nil; //destroy **my** ONLY strong reference to Mouse
}
NSLog(@"%@", computer.mouse); //prints (null)
......但也绝不会试图通过经验来诊断正确的所有权。这就是为什么retainCount
属性不再可用的原因。
编辑:扩展:getter的传统行为是返回一个非拥有引用,但仍保证至少与当前调用堆栈一样长。这样,在ARC之前的日子里,您可以直接使用getter来提供属性作为参数(在这种情况下,不会给调用者带来内存管理负担)或者获取调用者可以暂时保留的内容,即使原始所有者在此期间被解除分配(即经典自动释放池使用的东西有点像他们只是在堆栈上)。然后ARC只是实现了老式的规则,但是自动实现了完全的互操作性。