在 ARC 下,编译器将禁止使用-retainCount
,-retain
,-dealloc
,-release
和{{1}的任何方法或选择器}}
但有时候我想知道运行时的保留计数,或者使用方法调整来交换NSObject的-autorelease
方法来做某事。
是否有可能抑制(或绕过)编译器抱怨几行代码?我不想为整个项目或整个文件修改ARC环境。我认为预处理器可以做到,但是怎么做?
谢谢大家给我讲讲-dealloc
的用法。但我想知道是否可以强制调用/使用那些禁用的方法/选择器。
我知道-retainCount
是完成这项工作的强大工具。但我仍然对这些问题感到好奇。
Instruments
: 使用块时,如果未在外部变量上指定-retainCount
标识符,则在将块复制到堆中后,块将自动保留块中的外部对象。因此,您需要使用弱自我来避免保留周期,例如:
__weak
但是,当您仅在复制的块中使用实例变量时,它仍会导致保留周期(YES,尽管您未在块中使用任何关键字__weak typeof(self) weakSelf = self;
self.completionBlock = ^{
[weakSelf doSomething];
};
)。
例如,在非ARC :
下self
在复制的块代码之前/之后不使用// Current self's retain count is 1
NSLog(@"self retainCount: %d", [self retainCount]);
// Create a completion block
CompletionBlock completionBlock = ^{
// Using instance vaiable in the block will strongly retain the `self` object after copying this block into heap.
[_delegate doSomething];
};
// Current self's retain count is still 1
NSLog(@"self retainCount: %d", [self retainCount]);
// This will cuase retain cycle after copying the block.
self.completionBlock = completionBlock;
// Current self's retain count is 2 now.
NSLog(@"self retainCount: %d", [self retainCount]);
,我认为不会轻易发现在完成块中使用实例变量导致的保留周期。
-retainCount
: 我想知道是否可以使用方法调配来监视在调用-dealloc
时通过在Xcode控制台上记录消息来解除分配哪个对象。我想替换-dealloc
-dealloc
的原始实现。
答案 0 :(得分:23)
根本没有推荐,我不知道你的意图,但听起来不太安全。
不建议使用retainCount
。
来自AppleDocs:
此方法在调试内存管理问题时没有任何价值。 因为任何数量的框架对象都可能保留了一个对象 为了保持对它的引用,同时自动释放 池可能在一个对象上持有任意数量的延迟版本 你不太可能从这个方法中获得有用的信息
如果有任何疑问,请查看以下链接:
http://whentouseretaincount.com/
无论你想做什么,请不要。
对于将来的参考,我将添加一些linsk来帮助您了解内存在iOS中的工作方式。即使您使用ARC,也必须知道(请记住ARC不是垃圾收集器)
Beginning ARC in iOS 5 Tutorial Part 1
Understand memory management under ARC
Memory Management Tutorial for iOS
当然,一旦你理解了记忆是如何工作的,那么就该学习如何用乐器来描述它:
答案 1 :(得分:5)
与其他评论者100%同意您不想使用-retainCount
这一事实。但是,关于-dealloc
:
你也不想调动-dealloc
。如果你认为你想要调整它,你就不明白它是如何工作的。那里有很多优化;你不能只是搞乱它。但是,正如@bbum提示的那样,当对象被释放时,您可以轻松获得通知,这非常有用。
您将关联的对象附加到要观看的内容。当您想要观看的内容消失时,相关对象也会消失,您可以覆盖其dealloc
以执行您想要的任何操作。显然你需要小心一点,因为你处于dealloc
的中间,但你通常可以做任何你需要的东西。最重要的是,对于许多情况,您可以在此处设置断点或添加日志记录语句,以便查看对象的发布位置。这是一个简单的例子。
const char kWatcherKey;
@interface Watcher : NSObject
@end
#import <objc/runtime.h>
@implementation Watcher
- (void)dealloc {
NSLog(@"HEY! The thing I was watching is going away!");
}
@end
NSObject *something = [NSObject new];
objc_setAssociatedObject(something, &kWatcherKey, [Watcher new],
OBJC_ASSOCIATION_RETAIN);
const char kWatcherKey;
@interface Watcher : NSObject
- (void)lastRetainDone;
@end
#import <objc/runtime.h>
// turn off ARC!
@implementation Watcher
{
BOOL noMoreRetainsAllowed;
}
- (void)lastRetainDone {
noMoreRetainsAllowed = YES;
}
- (id) retain {
if (noMoreRetainsAllowed) abort();
return [super retain];
}
- (void)dealloc {
NSLog(@"HEY! The thing I was watching is going away!");
[super dealloc];
}
@end
...
NSObject *something = [NSObject new];
Watcher *watcher = [Watcher new];
objc_setAssociatedObject(something, &kWatcherKey, watcher,
OBJC_ASSOCIATION_RETAIN);
[watcher lastRetainDone];
[watcher release];
现在,当something
消失时,-[Watcher dealloc]
将会启动并为您登录。很容易。完全支持和记录。
编辑:
在复制的块代码之前/之后不使用-retainCount,我认为不会轻易发现在完成块中使用实例变量导致的保留周期。
你在这里有点正确,但有两个要吸取的教训,也就是使用retainCount
(在这种情况下实际上对你无实际帮助,因为retainCount
经常可以你没想到的东西。)