Objective c 使用块和幻象块参数交换的奇怪崩溃
我完全被这个问题难住了,希望有人能帮我: A类:Objective c 使用块和幻象块参数交换的奇怪崩溃,objective-c,cocoa,objective-c-blocks,Objective C,Cocoa,Objective C Blocks,我完全被这个问题难住了,希望有人能帮我: A类: - (void)setBlock:(BOOL(^)(id sender))block { myBlock = Block_copy(block); } - (BOOL)runBlock:(id)sender { myBlock(sender); } - (void)applicationDidFinishLaunching:(NSNotification *)aNotificationx { //The outer b
- (void)setBlock:(BOOL(^)(id sender))block {
myBlock = Block_copy(block);
}
- (BOOL)runBlock:(id)sender {
myBlock(sender);
}
- (void)applicationDidFinishLaunching:(NSNotification *)aNotificationx {
//The outer block provides behaviour according to strategy pattern:
[classAInstance setBlock:^BOOL(id sender) {
NSOperationQueue *queue = [[[NSOperationQueue alloc] init] autorelease];
//The inner block is a special case of behaviour where I want the task to run asynchronously:
[queue addOperationWithBlock:^(void) {
NSLog(@"sender: %@", [sender class]);
[sender doSomething];
}];
return YES;
}];
}
B类:
- (void)setBlock:(BOOL(^)(id sender))block {
myBlock = Block_copy(block);
}
- (BOOL)runBlock:(id)sender {
myBlock(sender);
}
- (void)applicationDidFinishLaunching:(NSNotification *)aNotificationx {
//The outer block provides behaviour according to strategy pattern:
[classAInstance setBlock:^BOOL(id sender) {
NSOperationQueue *queue = [[[NSOperationQueue alloc] init] autorelease];
//The inner block is a special case of behaviour where I want the task to run asynchronously:
[queue addOperationWithBlock:^(void) {
NSLog(@"sender: %@", [sender class]);
[sender doSomething];
}];
return YES;
}];
}
然后,当GUI事件导致classAInstance调用
-(BOOL)runBlock时代码>
(应该是这样)我得到了以下崩溃堆栈:
0 objc_exception_throw
3 __forwarding_prep_0___
4 __58-[ClassB applicationDidFinishLaunching:]_block_invoke_037
5 -[NSBlockOperation main]
11 start_wqthread
我得到的最后一个调试日志是:
sender: __NSMallocBlock__
-[__NSMallocBlock__ doSomething]: unrecognized selector sent to instance 0x10043f2a0
现在为什么block的参数突然变成了\uu NSMallocBlock\uu
?
很明显,我在向它传递其他东西(即发送方
),不是吗?调用runBlock时,您似乎在传递一个块作为发送方。我可以很好地运行你的代码。有一篇文章可以帮助你调试你的问题
如果复制NSStackBlock,它将返回NSMallocBlock
(指示其已更改的分配位置)
乔的回答似乎很有可能是对的。您还必须共享调用runBlock的代码,以便有人知道实际发生了什么,但鉴于您提供的方法的名称,它可能看起来像:
[classAInstance runBlock:^BOOL(id sender) {
// some code
}];
它实际上会打印NSStackBlock
(当然,除非首先复制块,在这种情况下,它将是NSMallocBlock
)
将产生以下结果:
sender: NSString
-[NSString doSomething]: unrecognized selector sent to instance
没有你的runBlock调用,尽管无法知道哪里出了问题。也可能是您使用正确的参数调用了该方法,但内存分配问题导致在您希望另一个对象存在的区域中分配了一个块,但这种可能性较小。这可能是您的问题:
NSOperationQueue *queue = [[[NSOperationQueue alloc] init] autorelease];
您正在创建一个NSOperationQueue,然后自动释放它,然后期望它为您工作。如果您希望在单独的线程中异步执行工作,请将dispatch_async()与并发队列一起使用:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^() {
NSLog(@"sender: %@", [sender class]);
[sender doSomething];
});
找到了原因。嗯,我现在觉得自己很愚蠢
错误是通过以下方式将块(以及第二个块)作为关联对象附着到我的对象:
static NSString * const FirstBlockKey;
static NSString * const SecondBlockKey;
objc_setAssociatedObject(self, FirstBlockKey, blockA, OBJC_ASSOCIATION_COPY);
objc_setAssociatedObject(self, SecondBlockKey, blockB, OBJC_ASSOCIATION_COPY);
虽然我应该清楚地使用这个:
objc_setAssociatedObject(self, (void *)&FirstBlockKey, block, OBJC_ASSOCIATION_COPY);
FirstBlockKey
和SecondBlockKey
本身显然都是0x0
,而它们自己的指针不是
这样,它只是调用了错误的块(因为它们都被分配到同一个“0x0”键)。这些块具有不同的返回和参数类型,这似乎导致了传递的块参数的奇怪交换。现在工作很好
话虽如此:乔,瑞安&白杨,谢谢你们的努力,伙计们 您键入的签名-(BOOL)runBlock代码>与代码示例不匹配。那是打字错误吗?为了一致性,runBlock不应该调用myFoo(发送方)代码>?:)是的,打字错误。现在应该修复了。您尝试过在块内初始化操作队列吗?@JoePasq:您的意思是在内部块内初始化队列?没有什么意义,是吗?@mtree您如何调用runBlock:
?好吧,如果您只想将它们用作地址,那么为什么还要麻烦让它们键入NSString*const
?它是什么类型或值似乎毫无意义