Как хранить блоки в Objective C?

Я начал писать простую библиотеку JSON RPC TCP в Objective C. У меня есть метод, который вызывает метод RPC:

- (void)invokeMethod:(NSString *)method
      withParameters:(id)parameters
           requestId:(id)requestId
             success:(void (^)(id responseObject))success
             failure:(void (^)(NSError *error))failure
{
    NSAssert(NSClassFromString(@"NSJSONSerialization"), @"NSJSONSerialization not found!");
    NSDictionary *requestObject = @{@"jsonrpc": @"2.0",
                                    @"method": method,
                                    @"params": parameters,
                                    @"id": requestId};
    NSError *error = nil;
    NSData *jsondData = [NSJSONSerialization dataWithJSONObject:requestObject options:0 error:&error];
    if (error){
        return failure(error);
    }
    [self->callbacks setObject:@{@"success": success ? [success copy] : [NSNull null],
                                 @"failure": failure ? [failure copy] : [NSNull null]}
                        forKey:requestId];
    NSString *str = [[NSString alloc] initWithData:jsondData encoding:NSUTF8StringEncoding];
    NSLog(@"Sending: %@", str);
    [self.socket writeData:jsondData withTimeout:-1 tag:1];
}

Класс в основном представляет TCP-соединение, при вызове вышеуказанного метода данные JSON отправляются с идентификатором через TCP на сервер, который либо возвращает успех, либо отказ:

- (void) socket:(GCDAsyncSocket *)sender didReadData:(NSData *)data withTag:(long)tag
{
    NSError *error = nil;
    [self.socket readDataWithTimeout:-1 tag:2];
    // … rpc response parsing code here, removed for simplicity …
    // detect if error or success
    NSDictionary *cbs = [self->callbacks objectForKey:JSONRPCObjectId];
    void(^success)(id resultObject) = [cbs objectForKey:@"success"];
    success ? success(JSONRPCObjectResult) : nil;
    return;
}

Теперь я не уверен, как отслеживать блоки success и failure, в настоящее время я храню их в NSMutableDict, используя requestId в качестве ключа. Можно ли это сделать или есть лучший подход, который я должен использовать?


person ePirat    schedule 18.08.2014    source источник
comment
@vikingosegundo Извините, как-то перепутал, отредактировал, чтобы исправить.   -  person ePirat    schedule 18.08.2014
comment
Почему бы просто не иметь два ivars/properties, один для успеха и один для неудачи?   -  person vikingosegundo    schedule 18.08.2014
comment
Проблема с TCP в том, что это постоянный поток, поэтому я не могу просто создавать новый объект для каждого запроса. Я мог бы создать новый объект для каждого вызова invokeMethod, но тогда мне понадобился бы способ их хранения и отслеживания, что на самом деле не решит проблему.   -  person ePirat    schedule 18.08.2014
comment
Я не вижу разницы, почему свойства не будут работать, но будут работать, сохраненные в словаре. вы должны дать нам (намного) больше деталей. И код.   -  person vikingosegundo    schedule 18.08.2014
comment
какова ваша минимальная целевая ОС, которую вам нужно протестировать для NSJSONSerialization? и когда вы удаляете блоки из словаря обратного вызова?   -  person vikingosegundo    schedule 18.08.2014
comment
При использовании свойств повторный вызов метода удалит предыдущие блоки, и если я получу ответ, из-за этого блок уже может исчезнуть. (Ответы могут приходить в любое время, поэтому я мог отправить invokeMethod с идентификатором 1, а другой с идентификатором 2, и сначала мог прийти идентификатор 2, а затем только тот, что для идентификатора 1)   -  person ePirat    schedule 18.08.2014
comment
Я удаляю их после звонка, когда получаю ответ. Может случиться так, что я никогда не получу ответа, я еще не нашел решения для этого…   -  person ePirat    schedule 18.08.2014
comment
У меня такое чувство, что ваш класс и так слишком много делает. но вы по-прежнему дали нам слишком мало информации, чтобы сделать больше, чем гадать.   -  person vikingosegundo    schedule 18.08.2014


Ответы (1)


Блоки в target-c являются объектами, и вы можете обращаться с ними так же, как и с другими объектами, поэтому их хранение в NSDictionarys, NSArrays и т. д. совершенно нормально. Единственная загвоздка в том, что блоки при первоначальном создании существуют в той же области памяти, что и локальная переменная, и поэтому они больше недействительны, когда метод, в котором определен блок, возвращает, как и все другие локальные переменные, поэтому вы должны сначала скопировать их , просто скопируйте их и поместите копию в коллекцию. Есть функция блочного копирования, но вы можете просто отправить им сообщение о копировании [myBlock copy];

person Nathan Day    schedule 18.08.2014
comment
мы можем предположить, что OP знает, как копировать в блок, поскольку он не просит помощи с несуществующими блоками. - person vikingosegundo; 18.08.2014