va_list、CVaListPointer、AnyObject和CVarArgType有何区别和用例?

15

问题

请问有人可以解释一下这些参数类型之间的区别吗?如果可能的话,请提供适当的使用案例(最好有代码演示,因为它能说服人)。

Nota bene

如果需要更多信息,请在评论中告诉我。

背景

我试图理解以下结构之间的任何差异,并了解适当的使用案例(如果有的话,请附带示例)。我在 SO、Google、et al.(博客圈)上搜索过,但没有找到令人满意的答案。

在编写数据存储对象时,我遇到了用于 NSPredicate 的以下初始化程序:

NSPredicate-initializers

Swift 头文件(1.2)指出:

CVaListPointer

一个博客评价指出在 Objective-C 中 va_list 的使用:

+ (void) log:(NSString *) format arguments:(va_list) argList
{
    [self logString: [NSString stringWithFormat: format arguments:
argList]];
}

+ (void) log:(NSString *) format, ...
{
    va_list argList;
    va_start(argList, format);
    {
  [self log: format arguments: argList];
    }
    va_end(argList);
}

CVarArgType是一个协议,根据Swift头文件可以按照以下方式使用。

CVarArgType

在我的自定义类中,我有以下用例:

   /*  Finds an array of entity in the MOC if any exists using an optional
    *   predicate with an array of arguments
    *
    *   Usage:
    *   eg. var items = CustomEntity.findInStore(dbStore, predicate:
    *   NSPredicate(format: "(attributeName IN %@)", argumentArray:
    *   ["value1","value2","value3"])) as? [CustomEntity]
    */

编辑:

请注意,argumentArray参数在我的自定义类中的使用方式是不正确的。为了正确使用这个初始化器,请查看苹果公司文档中以下内容:

argumentArray-doc

这将使我得以使用如下代码:

NSPredicate(format: "(%K != %@ AND %K = %@)", argumentArray: ["key1","value1","key2","value2"]) 
1个回答

21

va_list是一种用于可变参数函数的C类型。在Objective-C代码中,您会将其作为参数查看。

CVaListPointer是一个Swift等价于va_list的类型--无论何时在Objective-C中看到需要va_list作为参数的函数,您都需要在Swift中传递一个CVaListPointer

objective-c: (NSPredicate *)predicateWithFormat:(NSString *)format arguments:(va_list)argList
swift: init(format format: String, arguments argList: CVaListPointer) -> NSPredicate

CVarArgType是一个协议,定义了可以包含在CVaListPointer中的类型,包括所有原始类型(IntFloatUInt等)以及COpaquePointer

实用函数withVaList将Swift数组转换为CValListPointer,然后传递给回调函数。请注意,传入的数组必须仅包含CVarArgType变量:

var format = "%@ != %@"
var args: [CVarArgType] = ["abc", "def"]

var s = withVaList(args) { (pointer: CVaListPointer) -> NSPredicate in
    return NSPredicate(format: format, arguments: pointer)
}

Swift 还定义了自己的可变参数 T...,它必须作为函数中的最后一个参数,在函数中以 [T] 的形式传递,并且可以像下面这样使用。

var arg1: String = "abc"
var arg2: String = "def"
NSPredicate(format: format, arg1, arg2)

尽可能使用Swift内置的可变参数T...。只有在需要与接受va_list参数的Objective C和C APIs进行交互时才应使用CValListPointer


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接