如何在ARC下使用`-retainCount`方法和`-dealloc`选择器来强制执行? [英] How to enforce using `-retainCount` method and `-dealloc` selector under ARC?

查看:43
本文介绍了如何在ARC下使用`-retainCount`方法和`-dealloc`选择器来强制执行?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

ARC 下,编译器将禁止使用-retainCount-retain-dealloc-release-autorelease的任何方法或选择器.

Under ARC, compiler will forbid using any method or selector of -retainCount, -retain, -dealloc, -release, and -autorelease.

但是有时候我想知道运行时的保留计数,或者使用方法修改来交换NSObject的-dealloc方法来执行某些操作.

But sometimes I want to know the retain counts at runtime, or using method swizzling to swap the -dealloc method of NSObject to do something.

是否有可能抑制(或绕过)仅抱怨几行代码的编译器?我不想为整个项目或整个文件修改ARC环境.我认为预处理器可以做到,但是怎么办?

Is it possible to suppress (or bypass) the compiler complaining just a couple of lines of code? I don't want to modify ARC environment for whole project or whole file. I think preprocessor can do it, but how?

感谢大家给我一个关于-retainCount用法的课程.但是我不知道是否可以强制调用/使用那些禁止的方法/选择器.

Thanks guys to give me a lesson about the use of -retainCount. But I wonder whether it is possible to enforce invoking/using those forbidden methods/selectors.

我知道Instruments是执行此工作的强大工具.但是我仍然对那些问题感到好奇.

I know Instruments is a powerful tool to do this job. But I am still curious about those question.

使用块时,如果未在外部变量上指定__weak标识符,则在将块复制到堆中之后,该块将自动将那些外部对象保留在块中.因此,您需要使用弱自我来避免保留周期,例如:

When using block, if you don't specify a __weak identifier on the outside variables, the block will automatically retain those outside objects in the block after the block is copied into the heap. So you need to use a weak self to avoid retain cycle, for example:

__weak typeof(self) weakSelf = self;
self.completionBlock = ^{
    [weakSelf doSomething];
};

但是,当您仅在复制的块中使用实例变量时,它仍然会导致保留周期(是,尽管您没有在块中使用任何关键字self).

However, it will still cause retain cycle when you only use instance variables in the copied block (YES, although you didn't use any keyword self in the block).

例如,在非ARC 下:

// 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的情况下,我认为在完成块中使用实例变量导致的这种保留周期不会很容易被发现.

Without using -retainCount before/after the copied block code, I don't think this retain cycle caused by using instance variables in the completion block will be discovered easily.

我想知道是否可以通过调用-dealloc时在Xcode控制台上记录消息来使用方法刷新来监视将释放的对象.我想替换NSObject-dealloc的原始实现.

I want to know whether I can use method swizzling to monitor which object will be deallocated by logging messages on the Xcode console when the -dealloc is invoked. I want to replace the original implementation of -dealloc of NSObject.

推荐答案

与其他评论者达成100%的同意,即您不想使用-retainCount.但是,关于另一个问题,关于-dealloc:

Agreed 100% with the other commenters about the fact that you do not want to use -retainCount. To your other question, however, about -dealloc:

您也不想打扰-dealloc.如果您认为自己想麻烦,则不知道它是如何工作的.那里有很多优化.你不能只是把它弄乱.但是,正如@bbum所暗示的那样,当对象被释放时,您可以轻松地获得通知,这可能非常有用.

You also do not want to swizzle -dealloc. If you think you want to swizzle it, you don't understand how it works. There are a lot of optimizations going on there; you can't just mess with it. But, as @bbum hints at, you can easily get notifications when objects are deallocated, and this can be very useful.

您将关联的对象附加到要观看的对象上.当您要观看的东西消失时,关联的对象也消失了,您可以覆盖其dealloc以执行所需的任何操作.显然,您需要稍加小心,因为您位于dealloc的中间,但是通常您可以执行此处需要执行的大多数操作.在许多情况下,最重要的是,您可以在此处放置断点或添加日志记录语句,以便可以查看释放对象的位置.这是一个简单的例子.

You attach an associated object to the thing you want to watch. When the thing you want to watch goes away, so does the associated object, and you can override its dealloc to perform whatever action you want. Obviously you need to be a little careful, because you're in the middle of a dealloc, but you can generally do most anything you'd need to here. Most importantly for many cases, you can put a breakpoint here or add a logging statement, so you can see where the object was released. Here's a simple example.

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);

没有ARC

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]将启动并为您登录.非常简单.完全支持和记录.

Now, when something goes away, -[Watcher dealloc] will fire and log for you. Very easy. Completely supported and documented.

在复制的块代码之前/之后不使用-retainCount,我认为在完成块中使用实例变量引起的这种保留周期不会轻易被发现.

Without using -retainCount before/after the copied block code, I don't think this retain cycle caused by using instance variables in the completion block will be discovered easily.

您在这里是对的,但是有两个教训要学习,也不是使用retainCount(在这种情况下,这实际上对您没有帮助,因为retainCount通常可能是您不了解的东西)没想到).

You are somewhat correct here, but there are two lessons to be learned, and neither is to use retainCount (which won't actually help you in this case anyway because retainCount can very often be something you don't expect).

  • 第一课是:禁止ObjC代码中出现任何警告.您所描述的情况通常会在最新版本的clang中创建一个编译器警告.因此,实际上在很多情况下都很容易发现.您将其分为多个分配的方式,编译器可能会错过它,但是这里的课程是更改您的编码样式,以帮助编译器为您提供帮助.
  • 第二课是:不要在init和dealloc之外直接访问ivars.这是可能引起的许多小惊喜之一.使用访问器.

这篇关于如何在ARC下使用`-retainCount`方法和`-dealloc`选择器来强制执行?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆