具有主要类型和对象的 objc 可变参数

Posted

技术标签:

【中文标题】具有主要类型和对象的 objc 可变参数【英文标题】:objc variadic arguments with primary type and objects 【发布时间】:2014-12-04 11:06:49 【问题描述】:

我有一套底层api,如下:

- (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来包装底层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 是什么类型。它可能是一个 id、一个 BOOL、一个 int 或其他东西。 有没有更好的方法来重构更高层 api 中的复制粘贴代码? 任何提示表示赞赏!

【问题讨论】:

【参考方案1】:

您需要查看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

【讨论】:

别忘了[anInvocation retainArguments];,因为它是异步使用的。此外,还需要实现-methodSignatureForSelector:,尽管它应该是不言自明的。 谢谢!如果我将更高层的 api 稍微更改为:- (void) enableAutoRecord:(BOOL)isEnable withCompleteHandler:(CompleteHandler)completeHandler。如何从 anInvocation 中删除 arg completeHandler,以便 [anInvocation invokeWithTarget:self.lowerLayer];[self.lowerLayer respondsToSelector:[anInvocation selector]] 有效??

以上是关于具有主要类型和对象的 objc 可变参数的主要内容,如果未能解决你的问题,请参考以下文章

Kotlin泛型 ② ( 可变参数 vararg 关键字与泛型结合使用 | 使用 [] 运算符获取指定可变参数对象 )

可变长参数函数对象嵌套名称空间和作用域

Python 3 类型,具有任意数量的包含类型的自定义可变参数泛型,如何?

python函数的可变和不可变参数

函数的参数

Java基础-数组和面向对象