ARC 在 Xcode 和 Objective-C 中无法正常工作
ARC doesn't work properly in Xcode with Objective-C
我在使用 Obj-C 的 Xcode 中遇到了强引用和弱引用的两难选择。
当我创建两个内部相互交叉引用的对象时,所有对象都是弱的:
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之后;
在 "destroying" 对 Mouse class mouse 的唯一强引用之后,Mouse computer.mouse[= 的一个实例51=] 在应该被释放时仍然持有相同的内存地址。
只有 SWIFT 和 Xcode 中的完全相同的代码才能正常工作并释放 computer.mouse 持有的内存,使其成为 无
我的 Obj-c 代码有什么问题吗?我的 Xcode 是最新的,尽管使用以前的版本我在 Obj-c 中也没有运气。我将不胜感激任何帮助。
这是我的 classes:
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
您的 getter 正在自动合成,正在将它们 return 的对象放入自动释放池中。因此,您将 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 的传统行为预期是 return 非拥有引用,但保证至少与当前调用堆栈一样长。这样一来,在 ARC 之前的日子里,您可以直接使用 getters 来提供属性作为参数(在这种情况下,不要让调用者承担内存管理的负担)或获得调用者可以保留的东西短暂地,即使原来的所有者同时被释放(即经典的自动释放池使用,使事情表现得有点像它们只是在堆栈上)。然后 ARC 只是自动执行老式规则,以实现完全互操作性。
我在使用 Obj-C 的 Xcode 中遇到了强引用和弱引用的两难选择。 当我创建两个内部相互交叉引用的对象时,所有对象都是弱的:
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之后;
在 "destroying" 对 Mouse class mouse 的唯一强引用之后,Mouse computer.mouse[= 的一个实例51=] 在应该被释放时仍然持有相同的内存地址。
只有 SWIFT 和 Xcode 中的完全相同的代码才能正常工作并释放 computer.mouse 持有的内存,使其成为 无
我的 Obj-c 代码有什么问题吗?我的 Xcode 是最新的,尽管使用以前的版本我在 Obj-c 中也没有运气。我将不胜感激任何帮助。
这是我的 classes:
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
您的 getter 正在自动合成,正在将它们 return 的对象放入自动释放池中。因此,您将 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 的传统行为预期是 return 非拥有引用,但保证至少与当前调用堆栈一样长。这样一来,在 ARC 之前的日子里,您可以直接使用 getters 来提供属性作为参数(在这种情况下,不要让调用者承担内存管理的负担)或获得调用者可以保留的东西短暂地,即使原来的所有者同时被释放(即经典的自动释放池使用,使事情表现得有点像它们只是在堆栈上)。然后 ARC 只是自动执行老式规则,以实现完全互操作性。