将块保留在字典中
我有自己的方法,将块作为参数。我想在 NSDictionary 中跟踪该块。将块添加到字典的最佳方法是什么?
我尝试了这段代码,但执行下面的行(setObject ...)后,字典仍然是空的。我认为这是因为该块不是 NSObject 类型。但这样做的正确方法是什么?
- (void)startSomething:(NSURLRequest*)request block:(void (^)(NSURLResponse*, NSData*, NSError*))handler {
NSURLConnection *connection = [NSURLConnection connectionWithRequest:request delegate:self];
[pendingRequests setObject:handler forKey:connection];
}
编辑:
没关系。我不知道我在想什么。 3分:
- 块是objc对象
- 打字错误:setObject应该是setValue
- forKey是一个字符串所以它应该是[连接描述]或类似的东西
无论如何我现在解决了我的问题,如下所示:
- (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);
});
}
I have my own method that takes a block as an argument. I want to keep track of that block inside an NSDictionary. What is the best way to add the block to the dictionary?
I tried this code but after executing the line below (setObject...) the dictionary is still empty. I presume that is because the block is not of type NSObject. But what is the right way to do this?
- (void)startSomething:(NSURLRequest*)request block:(void (^)(NSURLResponse*, NSData*, NSError*))handler {
NSURLConnection *connection = [NSURLConnection connectionWithRequest:request delegate:self];
[pendingRequests setObject:handler forKey:connection];
}
EDIT:
Never mind. I don't know what I was thinking. 3 points:
- Blocks are objc objects
- Typo: setObject should be setValue
- forKey is a string so it should be [connection description] or something like that
Anyway I fixed my problem now like this:
- (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);
});
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
但这仍然行不通,或者充其量只是巧合地起作用。
在将处理程序放入字典之前,您需要复制它。类似于:
而且,是的,它应该是
setObject:forKey:
和objectForKey:
。That still isn't going to work or, at best, will only work coincidentally.
You need to copy the
handler
before shoving it in the dictionary. Something like:And, yes, it should be
setObject:forKey:
andobjectForKey:
.如果您使用 ARC,请使用
-copy
:If you are using ARC, use
-copy
:“错字:setObject 应该是 setValue”
不,您应该始终使用
setObject:
而不是setValue:
。setValue:
用于键值编码,并且巧合地与字典的setObject:
类似(即使如此,它也不一样,例如当键是时) @something"
),而setObject:
是将事物放入字典的正确方法,并且正确地将所有类型作为键。 (顺便说一句,我不确定您是否要使用connection
作为键,因为它会复制它。)真正的问题是,在将块存储在可能会发生错误的东西之前,需要先复制块 。持续时间比块的原始范围更长(这是块的特殊问题,而不是其他对象),因为块(与其他对象不同)最初位于堆栈上,因此保留它并不会阻止它被释放。将某些内容放入字典中通常会保留它,但在本例中这还不够。
"Typo: setObject should be setValue"
NO, you should always use
setObject:
instead ofsetValue:
.setValue:
is for key-value coding and coincidentally works similar tosetObject:
for a dictionary (even then, it's not the same, e.g. when the key is"@something"
), whilesetObject:
is the correct method for putting things in a dictionary, and which correctly takes all types as keys. (By the way I'm not sure you want to useconnection
as a key since it will copy it.)The real problem is that blocks need to be copied before you store them away in something that might last longer than the original scope of the block (this is a special issue for blocks and not for other objects), since blocks (unlike other objects) are initially on the stack, and thus retaining it does not prevent it from becoming deallocated. Putting something in a dictionary normally retains it, but that is not enough in this case.
实际上,使用 ARC,您可以简单地将块添加到 NSDictionary,就像使用任何其他对象一样。您不需要做任何特殊的事情,例如 Block_copy 或 [block copy],这样做是错误的并且会导致泄漏。
Actually with ARC you can simply add the block to the NSDictionary as you would with any other object. You do not need to do anything special like Block_copy or [block copy], and doing that would be wrong and will cause a leak.