2014-12-04 1 views
0

У меня есть набор нижнего уровня API, как показано ниже:ObjC аргументы VARIADIC с первичным типом и объекты

- (NSDictionary*) startRecord; 
- (NSDictionary*) stopRecord; 
- (NSDictionary*) switchMicrophone; 
- (NSDictionary*) enableAutoRecord:(BOOL)enable; 
- (NSDictionary*) deleteFile:(NSString*)filename; 
- (NSDictionary*) enableDatetimeStampOverlay:(BOOL)enable; 
- (NSDictionary*) setVideoResolution:(RESOLUTION_PARA)param; 
- (NSDictionary*) setExposureValue:(EXPOSURE_VALUE_PARA)param; 
- (NSDictionary*) setVolume:(VOLUME_PARA)param; 
- (NSDictionary*) setWifiConfigWithSsid:(NSString*)ssid AndPassword:(NSString*)password; 
- (NSDictionary*) formatSDCard; 
// ... the # of parameters are at most 3 

Я хотел бы создать более высокий уровень API, чтобы обернуть нижний слой апи, один из это, как показано ниже:

- (void) enableAutoRecord:(BOOL)isEnable 
{ 
    ... 
    dispatch_async(self.mySerialQueue, ^{ 
     ... 
     NSDictionary *response = [self.lowerLayer enableAutoRecord:isEnable]; 
     ... 
    }); 
} 

Для более высокого уровня, я обнаружил, что есть так много копировальной & пасты. Я надеюсь, что я могу переписать его, как показано ниже:

- (void) enableAutoRecord:(BOOL)isEnable 
{ 
    [self wrap_lower_layer_command:@"enableAutoRecord:", isEnable]; 
} 

Как написать «wrap_lower_layer_command»? Я изучил nsinvocation, objc_sendMsg и переменные аргументы. Но я застрял в проблеме типа. Возьмите вызов, например:

T arg = p1; 
[invocation setArgument:&arg atIndex:2]; 

Я не знаю, что такое тип p1. Это может быть идентификатор, или BOOL, или int, или что-то еще. Есть ли лучший способ реорганизовать копию & вставить код в api верхнего уровня? Любые подсказки оцениваются!

ответ

2

Необходимо изучить Message Forwarding.

- (void)forwardInvocation:(NSInvocation *)anInvocation 
{ 
    if ([self.lowerLayer respondsToSelector:[anInvocation selector]]) { 
     [anInvocation retainArguments]; // Thanks newacct 
     dispatch_async(self.mySerialQueue, ^{ 
      … 
      [anInvocation invokeWithTarget:self.lowerLayer]; 

      void *returnValue; 
      [invocation getReturnValue:&returnValue]; 
      NSDictionary *response = (__bridge NSDictionary *)returnValue; 
      … 
     }); 
    } else { 
     [super forwardInvocation:anInvocation]; 
    } 
} 

Я забыл включить часть о возвращаемом значении.


-retainArguments.

+0

Не забывайте '[anInvocation keepArguments];' поскольку он используется асинхронно. Кроме того, необходимо также реализовать '-methodSignatureForSelector:', хотя он должен быть довольно понятным. – newacct

+0

@newacct Спасибо за помощь! –

+0

Спасибо! Если бы я немного усовершенствовал api верхнего уровня, чтобы: '- (void) enableAutoRecord: (BOOL) isEnable withCompleteHandler: (CompleteHandler) completeHandler'. Как я могу удалить arg completeHandler из anInvocation, так что '[anInvocation invokeWithTarget: self.lowerLayer];' и '[self.lowerLayer отвечаетSoSelector: [anInvocation selector]]' действительны ?? – Arton