美文网首页iOS Developer程序员
FMDB中VA_LIST,NS_REQUIRES_NIL_TER

FMDB中VA_LIST,NS_REQUIRES_NIL_TER

作者: GiantAxe77 | 来源:发表于2017-02-20 18:12 被阅读113次

在此处踩过坑,故留记一下。

先看段代码:

- (BOOL)execute_insert_sql:(NSString *)sql,...NS_REQUIRES_NIL_TERMINATION{
    
    if (![self isOpenDB]) {
        if (self.dbPath.length) {
            BOOL open = [self openDBWithPath:self.dbPath];
            if (!open)
                return NO;
        }
        return NO;
    }
    
    __block BOOL success;
    va_list args;
    va_start(args, sql);
    id eachObject; 
    NSMutableArray* arr = [[NSMutableArray alloc] init];
    while ((eachObject = va_arg(args, id))) {
        [arr addObject:eachObject];
    }
    [self.dbQueue inDatabase:^(FMDatabase *db) {
        success = [db executeUpdate:sql withArgumentsInArray:arr];
        
    }];
    va_end(args);
    
    NSLog(@"execute_insert_sql:%@   fmdb_success:%d",sql,success);
    return success;
}

概念说明

NS_REQUIRES_NIL_TERMINATION

  • 源码如下:
#if !defined(NS_REQUIRES_NIL_TERMINATION)
    #if TARGET_OS_WIN32
        #define NS_REQUIRES_NIL_TERMINATION
    #else
        #if defined(__APPLE_CC__) && (__APPLE_CC__ >= 5549)
            #define NS_REQUIRES_NIL_TERMINATION __attribute__((sentinel(0,1)))
        #else
            #define NS_REQUIRES_NIL_TERMINATION __attribute__((sentinel))
        #endif
    #endif
#endif
  • attribute((sentinel)) 告知编译器需要一个结尾的参数,告知编译器参数的列表已经到最后一个不要再继续执行下去了
  • 最经常见到的应该是UIAlertView里用的了
- (id)initWithTitle:(NSString *)title message:(NSString *)message delegate:(id /*<UIAlertViewDelegate>*/)delegate cancelButtonTitle:(NSString *)cancelButtonTitle otherButtonTitles:(NSString *)otherButtonTitles, ... NS_REQUIRES_NIL_TERMINATION;  

VA_LIST,VA_START,VA_ARG,VA_END

  • ** VA_LIST是C语言中解决变参问题的一组宏,在头文件<stdarg.h>**中。
  • 用法:
    • 首先在函数里定义一具VA_LIST型的变量,这个变量是指向参数的指针;
    • 然后用VA_START宏初始化刚定义的VA_LIST变量;
    • 然后用VA_ARG返回可变的参数,VA_ARG的第二个参数是你要返回的参数的类型(如果函数有多个可变参数的,依次调用VA_ARG获取各个参数);
    • 最后用VA_END宏结束可变参数的获取。

下面造个轮子代码:

- (NSMutableArray *)setupArrWithObjects:(NSString *)arr1, ...NS_REQUIRES_NIL_TERMINATION
{
    NSMutableArray *arrM = [NSMutableArray array];
    va_list list;
    id tag;
    va_start(list, arr1);
    while ((tag = va_arg(list, id))) {
        [arrM addObject:tag];
    }
    va_end(list);
    return arrM;
}

- (void)viewDidLoad {
    [super viewDidLoad];

    NSMutableArray *arrM = [self setupArrWithObjects:@"arr1", @"arr2", @"arr3", nil];
    NSLog(@"arrM = %@", arrM);
}

注意点

  • 上述代码打印如下:
2017-02-20 17:43:42.305 argsTest[11260:282247] (
    arr2,
    arr3
)

因为第一个参数并不属于可变参数列表的一部分,所以va_start函数默认是从第一个参数以后开始扫描读取的。所以一般我们是手动处理第一个参数的,如下举个例子:

- (void)addObj:(id)firstObj,...NS_REQUIRES_NIL_TERMINATION
{
    NSMutableArray *array = [NSMutableArray array];
    if (firstObj)
    {
        va_list argsList;
        [array addObject:firstObj]; // 手动处理第一个参数
        va_start(argsList, firstObj);
        id arg;
        while ((arg = va_arg(argsList, id)))
        {
            [array addObject:arg];
        }
        va_end(argsList);
    }
    NSLog(@"array---%@", array);
}
  • 第二个注意的地方是使用- (NSMutableArray )setupArrWithObjects:(NSString )arr1, ...NS_REQUIRES_NIL_TERMINATION; 时,方法中如果不传入nil值会导致程序崩溃,因为在va_arg(argList, id))会一直取出值,在C语言中指针指向的即便是一个空内存地址未初始化也是会取出值的,那未初始化的内存空间赋值给可变数组就出现问题了,所以在使用- (NSMutableArray )setupArrWithObjects:(NSString )arr1, ...NS_REQUIRES_NIL_TERMINATION方法时在多参数的结尾一定要加上nil.

相关文章

  • FMDB中VA_LIST,NS_REQUIRES_NIL_TER

    在此处踩过坑,故留记一下。 先看段代码: 概念说明 NS_REQUIRES_NIL_TERMINATION 源码如...

  • 重要的宏定义

    typedef char* va_list;void va_start(va_list ap,prev_parm)...

  • va_list 可变参数用法及定义

    可变参数用法 上面是va_list的具体用法,下面讲解一下va_list各个语句含义和 va_list的实现。可变...

  • FFDB

    FMDB的使用 FMDBDemo 目录 1、FMDB介绍2、FMDB导入3、FMDB框架中重要的框架类3.1、FM...

  • iOS FMDB的使用

    FMDB在项目中的使用 一. 首先导入FMDB三方库:在podfile 文件中添 pod 'FMDB' 然后在...

  • C传递可变参数

    C传递可变参数 va_list   va_list配合va_start/va_arg/va_end宏定义, 可以完...

  • va_list 、va_start、 va_arg、 va_en

    在ANSI C中,这些宏的定义位于stdarg.h中: *typedef char va_list; va_sta...

  • iOS开发中va_list的应用

    va_list的定义: VA_LIST 是在C语言中解决变参问题的一组宏,所在头文件:#include ,用于获...

  • iOS总结1 - 数据库sqlite的使用

    一、集成测试环境 1.在github中搜索FMDB https://github.com/ccgus/fmdb2....

  • iOS FMDB增删改查

    FMDB是一款简洁、易用的封装库,下面简单介绍下FMDB的使用: 在FMDB下载文件后,导入工程中,并使用 lib...

网友评论

    本文标题:FMDB中VA_LIST,NS_REQUIRES_NIL_TER

    本文链接:https://www.haomeiwen.com/subject/widewttx.html