问题
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:
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.
来源:https://stackoverflow.com/questions/12310374/blocks-in-nsdictionary