将字块中的块保留
我有我自己的方法,把块作为一个参数。 我想跟踪在NSDictionary内的块。 将字块添加到字典的最佳方法是什么?
我试过这个代码,但执行下面的行(setObject …)后,字典仍然是空的。 我认为这是因为该块不是NSObjecttypes。 但是,这样做的正确方法是什么?
- (void)startSomething:(NSURLRequest*)request block:(void (^)(NSURLResponse*, NSData*, NSError*))handler { NSURLConnection *connection = [NSURLConnection connectionWithRequest:request delegate:self]; [pendingRequests setObject:handler forKey:connection]; }
编辑:
没关系。 我不知道我在想什么。 3分:
- 块是objc对象
- Typo:setObject应该是setValue
- forKey是一个string,所以它应该是[连接描述]或类似的东西
无论如何,我现在解决我的问题是这样的:
- (void)startSomething:(NSURLRequest*)request block:(void (^)(NSURLResponse*, NSData*, NSError*))handler { NSURLConnection *connection = [NSURLConnection connectionWithRequest:request delegate:self]; [pendingRequests setValue:handler forKey:[connection description]]; } - (void)connectionDidFinishLoading:(NSURLConnection *)connection { dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void) { void (^handler)(NSURLResponse*, NSData*, NSError*); handler = [pendingRequests valueForKey:[connection description]]; handler(nil, nil, nil); }); }
这仍然不起作用,或者至多只会巧合地工作。
您需要先复制handler
然后再放入字典中。 就像是:
void (^handlerCopy)(NSURLResponse*, NSData*, NSError*) = Block_copy(handler); [dict setObject:handlerCopy forKey:@"foo"]; Block_release(handlerCopy); // dict will -retain/-release, this balances the copy.
而且,是的,它应该是setObject:forKey:
和objectForKey:
如果您正在使用ARC,请使用-copy
:
void (^handlerCopy)(NSURLResponse*, NSData*, NSError*) = [handler copy]; [dict setObject:handlerCopy forKey:@"foo"];
“Typo:setObject应该是setValue”
不,你应该总是使用setObject:
而不是setValue:
setValue:
用于键值编码,与setObject:
类似setObject:
对于字典(即使这样,它不是相同的,例如当键是"@something"
),而setObject:
是将东西放入字典,并正确把所有types作为关键。 (顺便说一句,我不知道你想用connection
作为一个关键,因为它会复制它。)
真正的问题在于,在将块存储在可能比块的原始范围更长的东西(这是块的特殊问题而不是其他对象)之前,块需要被复制,因为块(不像其他对象)最初是在栈上,因此保留它并不妨碍它被释放。 把一些东西放在字典中通常会保留,但在这种情况下还不够。
[pendingRequests setObject:[[handler copy] autorelease] forKey:connection];
实际上,使用ARC,您可以简单地将块添加到NSDictionary,就像使用其他对象一样。 你不需要像Block_copy或[block copy]那样做任何特殊的事情,这样做是错误的,会导致泄漏。