我正在阅读杰夫凯利的这篇文章并试图做同样的事情。但是代码是在ARC被采用之前编写的,现在无法编译。
主要问题是打印输出的这一部分,一些播放错误,然后阻止发布消息。我发现这是一个非常有趣的例子,但我似乎无法让它发挥作用。
问题是:
0。自动合成属性'阻止'将使用合成的实例变量' _block',而不是现有的实例变量' block' on @implementation JKBlockExecutor
1。块指针类型的转换' voidBlock' (又名' void(^)(void)')到C指针类型' const void *'需要桥接演员和 C指针类型的演员' void *'阻止指针类型' typeof(aBlock)' (aka' void(^ __ strong)(void)')需要一个桥接演员" 块= Block_copy(aBlock);的行
2。块指针类型的转换' voidBlock' (又名' 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];
这段代码能以某种方式修复吗?我拿出所有的发布消息都无济于事。
答案 0 :(得分:1)
下面的代码构建和工作(或至少看起来如此),并打印“Deallocating 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;
答案 1 :(得分:0)
如果您想了解有关以下代码的更多信息,请转到Fun With the Objective-C Runtime: Run Code at Deallocation of Any Object
第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部分:核心代码:使用runtime来实现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!");
}];