将块保留在字典中

发布于 2024-11-16 03:56:39 字数 1258 浏览 4 评论 0原文

我有自己的方法,将块作为参数。我想在 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分:

  1. 块是objc对象
  2. 打字错误:setObject应该是setValue
  3. 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:

  1. Blocks are objc objects
  2. Typo: setObject should be setValue
  3. 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

天荒地未老 2024-11-23 03:56:39

但这仍然行不通,或者充其量只是巧合地起作用。

在将处理程序放入字典之前,您需要复制它。类似于:

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:

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:

void (^handlerCopy)(NSURLResponse*, NSData*, NSError*) = Block_copy(handler);
[dict setObject:handlerCopy forKey:@"foo"];
Block_release(handlerCopy); // dict will -retain/-release, this balances the copy.

And, yes, it should be setObject:forKey: and objectForKey:.

往日 2024-11-23 03:56:39

如果您使用 ARC,请使用 -copy

 void (^handlerCopy)(NSURLResponse*, NSData*, NSError*) = [handler copy];
 [dict setObject:handlerCopy forKey:@"foo"];

If you are using ARC, use -copy:

 void (^handlerCopy)(NSURLResponse*, NSData*, NSError*) = [handler copy];
 [dict setObject:handlerCopy forKey:@"foo"];
长途伴 2024-11-23 03:56:39

“错字:setObject 应该是 setValue”

不,您应该始终使用 setObject: 而不是 setValue:setValue: 用于键值编码,并且巧合地与字典的 setObject: 类似(即使如此,它也不一样,例如当键是 时) @something"),而 setObject: 是将事物放入字典的正确方法,并且正确地将所有类型作为键。 (顺便说一句,我不确定您是否要使用connection作为键,因为它会复制它。)

真正的问题是,在将块存储在可能会发生错误的东西之前,需要先复制块 。持续时间比块的原始范围更长(这是块的特殊问题,而不是其他对象),因为块(与其他对象不同)最初位于堆栈上,因此保留它并不会阻止它被释放。将某些内容放入字典中通常会保留它,但在本例中这还不够。

[pendingRequests setObject:[[handler copy] autorelease] forKey:connection];

"Typo: setObject should be setValue"

NO, you should always use setObject: instead of setValue:. setValue: is for key-value coding and coincidentally works similar to setObject: for a dictionary (even then, it's not the same, e.g. when the key is "@something"), while setObject: 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 use connection 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.

[pendingRequests setObject:[[handler copy] autorelease] forKey:connection];
最初的梦 2024-11-23 03:56:39

实际上,使用 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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文