blocks in nsdictionary?

2020-07-14 06:13发布

So I'm storing block actions into a nsmutabledictionary and then recalling them when a response comes back on a websocket. This turns async request into a block syntax. Here's the stripped down code:

- (void)sendMessage:(NSString*)message responseAction:(void (^)(id))responseAction
{ 
    NSString *correlationID =  (NSString*)[[message JSONValue] objectForKey:@"correlationId"];

    [self.messageBlocks setObject:responseAction forKey:correlationID];

    NSLog(@"Sending message: %@", correlationID);
   [webSocket send:message];
}

- (void)webSocket:(SRWebSocket *)wsocket didReceiveMessage:(id)message;
{
    NSString *correlationID = (NSString*)[[message JSONValue] objectForKey:@"correlationId"];
    NSLog(@"Incoming message. CorrelationID: %@", correlationID);
    void (^action)(id) = nil;
    if (correlationID) {
        action = [messageBlocks objectForKey:correlationID];
        if (action) action([message JSONValue]);
        [messageBlocks removeObjectForKey:correlationID];
    }
}

Note: The server responds with a correlationID that is sent with the request. So each response is linked to each request through that id.

This works perfectly, better than I expected. The question I have is that is it safe to run blocks this way? Is calling [messageBlocks removeObjectForKey:correlationID]; enough to remove it from the memory. I remember pre-ARC, block_release was an option.

1条回答
虎瘦雄心在
2楼-- · 2020-07-14 07:00

You need to copy stack-based blocks in order to safely store them in a container.

[self.messageBlocks setObject:[responseAction copy] forKey:correlationID];

For non-ARC code, you need to -autorelease it also.

[self.messageBlocks setObject:[[responseAction copy] autorelease] forKey:correlationID];

Hope that helps.

查看更多
登录 后发表回答