在取消分配任何对象时运行代码
我正在阅读杰夫凯利的这篇文章,并试图做同样的事情。 然而,代码是在ARC被采纳之前编写的,现在无法编译。
http://blog.slaunchaman.com/2011/04/11/fun-with-the-objective-c-runtime-run-code-at-deallocation-of-any-object/
主要问题是在打印输出的这一部分,一些铸造错误,然后阻止释放信息。 我发现它是一个非常有趣的例子,但我似乎无法得到它的工作。
问题是:
0.自动合成属性'block'将在 @implementation JKBlockExecutor 上使用合成的实例变量'_block',而不是现有的实例变量'block'
1.将块指针类型'voidBlock'(aka'void(^)(void)')转换为C指针类型'const void *'需要桥接转换和 Cast of C指针类型'void *'来阻止指针类型' typeof运算(ABLOCK)”(又名'空隙(^ __强)(无效)')需要在块= Block_copy(ABLOCK)的桥连铸”; 线
2.块指针类型'voidBlock'(aka'void(^)(void)')转换为C指针类型'const void *'需要在 Block_release(block) 上进行桥接转换。
typedef void (^voidBlock)(void);
@interface JKBlockExecutor : NSObject {
voidBlock block;
}
@property (nonatomic, readwrite, copy) voidBlock block;
- (id)initWithBlock:(voidBlock)block;
@end
@implementation JKBlockExecutor
@synthesize block;
- (id)initWithBlock:(voidBlock)aBlock
{
self = [super init];
if (self) {
block = Block_copy(aBlock);
}
return self;
}
- (void)dealloc
{
if (block != nil) {
block();
Block_release(block);
}
[super dealloc];
}
@end
这是他在NSObject上创建一个类别的地方。
const void *runAtDeallocBlockKey = &runAtDeallocBlockKey;
@interface NSObject (JK_RunAtDealloc)
- (void)runAtDealloc:(voidBlock)block;
@end
@implementation NSObject (JK_RunAtDealloc)
- (void)runAtDealloc:(voidBlock)block
{
if (block) {
JKBlockExecutor *executor = [[JKBlockExecutor alloc] initWithBlock:block];
objc_setAssociatedObject(self,
runAtDeallocBlockKey,
executor,
OBJC_ASSOCIATION_RETAIN);
[executor release];
}
}
@end
这就是你如何执行这个例子。
NSObject *foo = [[NSObject alloc] init];
[foo runAtDealloc:^{
NSLog(@"Deallocating foo!");
}];
[foo release];
或另一种获取其他信息的方式。
NSObject *foo = [[NSObject alloc] init];
__block id objectRef = foo;
[foo runAtDealloc:^{
NSLog(@"Deallocating foo at address %p!", objectRef);
}];
[foo release];
该代码可以以某种方式修复吗? 我拿出所有的发布消息都无济于事。
下面的代码构建和工作(或至少看起来如此),并打印出“释放foo!”。 当我期望它打印它。 第1部分:
typedef void (^voidBlock)(void);
@interface JKBlockExecutor : NSObject {
voidBlock block;
}
@property (nonatomic, readwrite, copy) voidBlock block;
- (id)initWithBlock:(voidBlock)block;
@end
@implementation JKBlockExecutor
@synthesize block = block;
- (id)initWithBlock:(voidBlock)aBlock
{
self = [super init];
if (self) {
block = [aBlock copy];
}
return self;
}
- (void)dealloc
{
if (block != nil) {
block();
block = nil;
}
}
@end
第2部分:
const void *runAtDeallocBlockKey = &runAtDeallocBlockKey;
@interface NSObject (JK_RunAtDealloc)
- (void)runAtDealloc:(voidBlock)block;
@end
@implementation NSObject (JK_RunAtDealloc)
- (void)runAtDealloc:(voidBlock)block
{
if (block) {
JKBlockExecutor *executor = [[JKBlockExecutor alloc] initWithBlock:block];
objc_setAssociatedObject(self,
runAtDeallocBlockKey,
executor,
OBJC_ASSOCIATION_RETAIN);
}
}
@end
测试它是否有效:
@autoreleasepool {
NSObject *foo = [[NSObject alloc] init];
[foo runAtDealloc:^{
NSLog(@"Deallocating foo!");
}];
}
编辑
改变了Block_release(block);
block = nil;
如果您想了解更多关于下面的代码的知识,请访问Objective-C运行库:运行代码解除任何对象的释放
第1部分:创建一个类:我们想要释放的对象何时发生---这个类就像一个事件:当目标obj dealloc发生时,使用阻止来执行事件。
// .m file
// http://weibo.com/luohanchenyilong/
// https://github.com/ChenYilong
// the object We Want To Be Released When That Happens--- this class is like an event:when the target obj dealloc,it happens。use block to execute the event 。
typedef void (^voidBlock)(void);
@interface CYLBlockExecutor : NSObject
- (id)initWithBlock:(voidBlock)block;
@end
// .m file
// http://weibo.com/luohanchenyilong/
// https://github.com/ChenYilong
// the object We Want To Be Released When That Happens--- this class is like an event:when the target obj dealloc,it happens。use block to execute the event 。
#import "CYLBlockExecutor.h"
@interface CYLBlockExecutor() {
voidBlock _block;
}
@implementation CYLBlockExecutor
- (id)initWithBlock:(voidBlock)aBlock
{
self = [super init];
if (self) {
_block = [aBlock copy];
}
return self;
}
- (void)dealloc
{
_block ? _block() : nil;
}
@end
第2部分:核心代码:使用运行时来实现cyl_runAtDealloc方法
// CYLNSObject+RunAtDealloc.h file
// http://weibo.com/luohanchenyilong/
// https://github.com/ChenYilong
// use runtime to realize cyl_runAtDealloc method
#import "CYLBlockExecutor.h"
const void *runAtDeallocBlockKey = &runAtDeallocBlockKey;
@interface NSObject (CYLRunAtDealloc)
- (void)cyl_runAtDealloc:(voidBlock)block;
@end
// CYLNSObject+RunAtDealloc.m file
// http://weibo.com/luohanchenyilong/
// https://github.com/ChenYilong
// use runtime to realize cyl_runAtDealloc method
#import "CYLNSObject+RunAtDealloc.h"
#import "CYLBlockExecutor.h"
@implementation NSObject (CYLRunAtDealloc)
- (void)cyl_runAtDealloc:(voidBlock)block
{
if (block) {
CYLBlockExecutor *executor = [[CYLBlockExecutor alloc] initWithBlock:block];
objc_setAssociatedObject(self,
runAtDeallocBlockKey,
executor,
OBJC_ASSOCIATION_RETAIN);
}
}
@end
如何使用 :
#import "CYLNSObject+RunAtDealloc.h"
然后
NSObject *foo = [[NSObject alloc] init];
[foo cyl_runAtDealloc:^{
NSLog(@"Deallocating foo!");
}];
链接地址: http://www.djcxy.com/p/44915.html