5

ブロックアクションをnsmutabledictionaryに格納してから、応答がwebsocketに戻ったときにそれらをリコールします。これにより、非同期要求がブロック構文に変換されます。ブロック?

- (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]; 
    } 
} 

注:サーバーは要求と共に送信されたcorrelationIDで応答します。したがって、各応答はそのIDを介して各要求にリンクされます。

これは、私が予想したよりもはるかに優れています。私が持っている質問は、この方法でブロックを実行することは安全ですか? [messageBlocks removeObjectForKey:correlationID]を呼び出しています。それをメモリから取り除くのに十分です。私はpre-ARCを覚えています、block_releaseはオプションでした。

答えて

8

スタックベースのブロックをコンテナに安全に保管するためには、スタックベースのブロックをコピーする必要があります。

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

非ARCコードの場合は、-autoreleaseも必要です。

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

希望します。