ios - 圆弧 : how to inject custom dealloc IMP in object which in turn calls original dealloc without causing malloc error

标签 ios objective-c cocoa-touch cocoa

我正在尝试执行以下操作:

  1. 获得类'dealloc IMP
  2. 向所述类中注入(inject)一个自定义 IMP,它基本上调用原始的 dealloc IMP
  3. 当所述类的一个实例被释放时,两个 IMP 都应该运行。

这是我的尝试:

@implementation ClassB

- (void)dealloc
{
    NSLog(@"\n%@ | %@", self, NSStringFromSelector(_cmd));
}

@end


@implementation ClassC

- (void)swizzleMe:(id)target
{
    SEL originalDeallocSelector = NSSelectorFromString(@"dealloc");
    __block IMP callerDealloc = [target methodForSelector:originalDeallocSelector];
    const char *deallocMethodTypeEncoding = method_getTypeEncoding(class_getInstanceMethod([target class], originalDeallocSelector));
    IMP newCallerDealloc = imp_implementationWithBlock(^(id _caller) {
        NSLog(@"\n new dealloc | calling block %p for %@", callerDealloc, _caller);
        callerDealloc(_caller, originalDeallocSelector);
    });

    NSLog(@"\nswapping %p for %p", newCallerDealloc, callerDealloc);

    class_replaceMethod([target class],
                        originalDeallocSelector,
                        newCallerDealloc,
                        deallocMethodTypeEncoding);

}

@end

像这样使用:

ClassB *b = [[ClassB alloc] init];
ClassC *c = [[ClassC alloc] init];
[c swizzleMe:b];

但是结果是:

禁用僵尸对象:

2013-07-03 13:24:58.368 runtimeTest[38626:11303] 
swapping 0x96df020 for 0x2840
2013-07-03 13:24:58.369 runtimeTest[38626:11303] 
 new dealloc | calling block 0x2840 for <ClassB: 0x93282f0>
2013-07-03 13:24:58.370 runtimeTest[38626:11303] 
<ClassB: 0x93282f0> | dealloc
2013-07-03 13:24:58.370 runtimeTest[38626:11303] 
 new dealloc | calling block 0x2840 for <ClassB: 0x93282f0>
2013-07-03 13:24:58.371 runtimeTest[38626:11303] 
<ClassB: 0x93282f0> | dealloc
runtimeTest(38626,0xac55f2c0) malloc: *** error for object 0x93282f0: pointer being freed was not allocated
*** set a breakpoint in malloc_error_break to debug
2013-07-03 13:24:58.371 runtimeTest[38626:11303] 
 new dealloc | calling block 0x2840 for <ClassB: 0x93282f0>
2013-07-03 13:24:58.372 runtimeTest[38626:11303] 
<ClassB: 0x93282f0> | dealloc

启用僵尸对象(图中第11行是一个EXC_BAD_ACCESS)

2013-07-03 13:34:37.466 runtimeTest[38723:11303] 
swapping 0x97df020 for 0x2840
2013-07-03 13:34:37.467 runtimeTest[38723:11303] 
 new dealloc | calling block 0x2840 for <ClassB: 0x715a920>
2013-07-03 13:34:37.468 runtimeTest[38723:11303] 
<ClassB: 0x715a920> | dealloc

有没有想过我做错了什么?

Line 11 is a EXC_BAD_ACCESS

最佳答案

如果你真的想知道一个对象何时被释放,那么使用关联对象。

具体来说,将一个对象与您要观察的对象相关联,以便被观察的对象对该对象具有唯一的强引用——唯一的保留引用。然后,您可以覆盖 dealloc 并知道当它被调用时,被观察的对象已经(或即将)被释放。

不过,不要弄乱被释放的对象!它已经调用了所有的 dealloc 方法(通过继承),因此,内部状态将完全未定义。

请注意,如果您的目标是尝试清理系统框架中的某些内容,那么……不要这样做。沿着这条路走下去,没有任何不稳定和痛苦。


like I mentioned in the comments to nielsbot, I am NOT trying to know when an object is deallocated.

准确了解注入(inject)的 dealloc 实现中的内容会很有帮助。从表面上看,我认为无法通过使用关联对象来检测释放来解决的唯一原因正是因为您正试图更改类的行为 dealloc,这是一件非常糟糕的事情。

关于ios - 圆弧 : how to inject custom dealloc IMP in object which in turn calls original dealloc without causing malloc error,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17457694/

相关文章:

ios - Swift框架与Cocoapods——整合静态库

iphone - 这两个init方法有什么区别?

objective-c - 使用 Core Data 时提高 UI 性能

ios - 在 iOS 应用中使用 Office365 SDK 进行静默登录

ios - Swift 类扩展 - 发送到实例的无法识别的选择器

ios - 如何在Ios中获取视频的Instagram Media_ID?

Iphone 应用程序开发 - 如何重新加载(?) View ?

ios - UICollectionViewFlowLayout 子类在滚动和重新加载时崩溃访问超出范围的数组

iphone - 主线程在SCNetworkReachabilityGetFlags上被阻止

objective-c - 如何在 iOS 中以编程方式编写带有音频文件的彩信?