文档章节

Objective-C中编写省略参数的多参函数

珲少
 珲少
发布于 2015/05/04 10:41
字数 920
阅读 2421
收藏 50

【推荐】2019 Java 开发者跳槽指南.pdf(吐血整理) >>>

Objective-C中编写省略参数的多参数函数

引语:

在Object-C中,我们会遇到很多像NSLog这样的函数,其中参数的个数不确定,由程序员自由控制,在初始化数组,字典等方面应用广泛,那么,这类的函数是如何实现的呢?我们怎么编写我们自己的省略参数的函数呢?当然,这不是唯一的多参函数的处理方法,你也可以通过一个字典或者数组传递参数。但C为我们提供的这样的一种机制,无疑是最方便的。

一、了解几个概念

va_list

C语言中定义的一个指针,用于指向当前的参数。

 

 

va_start(ap,param)

 

这个宏是初始化参数列表,其中第一个参数是va_list对象,第二个参数是参数列表的第一个参数。

 

 

 

va_arg(ap, type)

 

一个用于取出参数的宏,这个宏的第一个参数是va_list对象,第二个参数是要取出的参数类型。

 

 

va_end(ap)

 

这个宏用于关闭取参列表

 

二、多参函数的取参原理

在编写我们自己的多参函数之前,明白函数的取参原理是十分重要的,首先,函数的参数是被放入我们内存的栈段的,而且放入的顺序是从后往前放入,比如如果一个函数参数如下:

void func(int a,int b,int c,int d)

那么传递参数的时候参数d先入栈,接着是c、b、a。如此这样,在取参的时候,根据堆栈的取值原则,则取值顺序为a、b、c、d。所以在原理上,只要我们知道第一个参数的地址和每个参数的类型,我们就可以将参数都取出来。而上面介绍的几个宏,就是帮助我们做这些的。
 

三、声明与实现省略参数的多参函数

"..."这个符号就是我们用来实现省略参数函数的符号。例如我们模拟实现一个log函数如下:

-(void)myLog:(NSString *)str,...{//省略参数的写法
    va_list list;//创建一个列表指针对象
    va_start(list, str);//进行列表的初始化,str为省略前的第一个参数,及...之前的那个参数
    NSString * temStr = str;
    while (temStr!=nil) {//如果不是nil,则继续取值
         NSLog(@"%@",temStr);
         temStr = va_arg(list, NSString*);//返回取到的值,并且让指针指向下一个参数的地址
    }
    va_end(list);//关闭列表指针
}

注意,调用时,我们必须在参数的最后加上nil这个判断结束的条件:

[self myLog:@"312",@"321", nil];//必须有nil

四、一点补充

细心的你可能发现了,这里的nil是我们在调用函数时手动加上的,可是系统的许多函数在我们调用时,系统直接帮我们加上了参数结尾的那个nil,例如

 

 NSArray * array = [NSArray arrayWithObjects:(id), nil]

这是如何做到的呢?我们只需要在函数的声明里加上一个宏,就可以实现这个功能,修改如下:

-(void)myLog:(NSString *)str,...NS_REQUIRES_NIL_TERMINATION{//这里加上一个宏
    va_list list;
    va_start(list, str);
    NSString * temStr = str;
    while (temStr!=nil) {
         NSLog(@"%@",temStr);
         temStr = va_arg(list, NSString*);
    }
    va_end(list);
}

顾名思义,这个宏的作用就是在结束位置加上我们需要的nil。

专注技术,热爱生活,交流技术,也做朋友。

——珲少 QQ群:203317592

© 著作权归作者所有

珲少

珲少

粉丝 891
博文 395
码字总数 478712
作品 0
上海
程序员
私信 提问
加载中

评论(3)

珲少
珲少 博主

引用来自“AllanChan”的评论

请问这种传参的方式是在什么时候用的上?可以举例子吗?这样写代码的话,代码的可读性不是会变差????请指正!!

对于参数数量不确定,就像AlertView创建时传递的按钮标题,当然,你也可以通过字典或者数组完成这类的参数传递,但是相比较起来,这是一种简单的方式。0
开源中国真理部部长
开源中国真理部部长

引用来自“AllanChan”的评论

请问这种传参的方式是在什么时候用的上?可以举例子吗?这样写代码的话,代码的可读性不是会变差????请指正!!
print(),NSLog() 等函数都使用这种方式,一般在你编写类库时用到的机会会更大。
AllanChan
AllanChan
请问这种传参的方式是在什么时候用的上?可以举例子吗?这样写代码的话,代码的可读性不是会变差????请指正!!
Swift解读专题一——Swift2.2语言预览

专题一——Swift2.2语言预览 一、引言 本系列专题是我通过阅读Swift2.2语言开发文档,翻译总结加上自己的理解整理而成。其中大部分结构和内容都来自开发文档,有疏漏和错误之处,还望更多朋友...

珲少
2016/05/05
840
0
Swift讲解专题七——函数

Swift讲解专题七——函数 一、引言 函数是有特定功能的代码段,函数会有一个特定的名称调用时来使用。Swift提供了十分灵活的方式来创建与调用函数。事实上在Swift,每个函数都是一种类型,这...

珲少
2016/05/13
389
1
《从零开始学Swift》学习笔记(Day 70)——Swift与Objective-C混合编程之

《从零开始学Swift》学习笔记(Day 70)——Swift与Objective-C混合编程之Swift与Objective-CAPI映射 原创文章,欢迎转载。转载请注明:关东升的博客 Swift与Objective-C API映射 在混合编程...

智捷课堂
2016/02/26
44
0
《从零开始学Swift》学习笔记(Day 70)——Swift与Objective-C混合编程之Swift与Objective-CAPI映射

原创文章,欢迎转载。转载请注明:关东升的博客 Swift与Objective-C API映射 在混合编程过程中Swift与Objective-C调用是双向的,由于不同语言对于相同API的表述是不同的,他们之间是有某种映...

tony关东升
2018/06/26
0
0
《Objective-C高级编程》温故知新之"Blocks"

前言 很久前看了《Objective-C高级编程 iOS与OS X多线程和内存管理》这本书,但当时看起来晦涩难懂。最近利用下班时间重读了一遍,觉得还是得记录一下。毕竟每个阶段对相同的东西会有更深刻的...

Dwyane_Coding
2018/08/28
0
0

没有更多内容

加载失败,请刷新页面

加载更多

在每个GROUP BY组中选择第一行?

顾名思义,我想选择以GROUP BY分组的每组行的第一行。 具体来说,如果我有一个如下的purchases表: SELECT * FROM purchases; 我的输出: id | customer | total---+----------+------ 1...

技术盛宴
33分钟前
5
0
python 安装与使用总结

https://www.jetbrains.com/pycharm/download/#section=mac

T型人才追梦者
37分钟前
5
0
每个开发人员都应该知道的11个Linux命令

本文主要挑选出读者有必要首先学习的 11 个 Linux 命令,如果不熟悉的读者可以在虚拟机或云服务器上实操下,对于开发人员来说,能熟练掌握 Linux 做一些基本的操作是必要的! 事不宜迟,这里...

武培轩
46分钟前
7
0
window.onload与$(document).ready()

JavaScript的window.onload和jQuery的$(document).ready()方法有什么区别? #1楼 关于在Internet Explorer中使用$(document).ready()的警告。 如果在整个文档加载之前 HTTP请求被中断(例如,...

javail
49分钟前
8
0
对比yml配置文件与properties的区别

我们在日常编码中少不了配置文件,说到配置文件就不得不说起yml和properties这两种后缀的配置文件 接下来我带大家简述一下他们具体有什么区别 - yml格式的文件 server: port: 9090 spring: a...

理性思考
52分钟前
7
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部