Каковы различия и варианты использования для va_list, CVaListPointer, AnyObject..., CVarArgType?

Вопрос

Может кто-нибудь объяснить различия между этими типами аргументов? Кроме того, если возможно, поставьте соответствующие прецеденты с использованием кода (это стоит 1000 слов).

Nota bene

Пожалуйста, дайте мне знать в комментариях, если есть какие-либо требования для получения дополнительной информации.

Фон

Я пытаюсь понять любые различия между следующими конструкциями и понять соответствующие варианты использования (с примерами, если они есть). Я искал SO, Google, et, al. (блогосфера), не найдя удовлетворительного ответа.

При написании объекта хранилища данных я натолкнулся на следующие инициализаторы для NSPredicate:

NSPredicate-initializers

В файле заголовка Swift (1.2):

CVaListPointer

Комментарий в блоге указывает на следующее использование va_list в Objective-C

+ (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]
    */

EDIT:

Читатели учтут, что параметр argumentArray был неправильно использован, как описано в моем пользовательском классе. Чтобы правильно использовать этот инициализатор, обратите внимание на следующее из документации Apple:

argumentArray-doc

Что приводит меня к этому использованию:

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

Ответ 1

va_list - это тип C, используемый для переменных функций аргументов. Вы увидите это как параметр в коде Objective-C.

CVaListPointer является быстрым эквивалентом a va_list - везде, где вы видите функцию в Objective-C, которая принимает va_list в качестве аргумента, вы передаете CVaListPointer в Swift.

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

CVarArgType - это протокол, который определяет, какие типы могут быть включены в CVaListPointer, включая все примитивы (Int, Float, UInt и т.д.), а также 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 также определяет свой собственный параметр varadic T..., который должен быть последним параметром в функции, он передается в функцию как [T] и используется так.

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

Используйте Swift, встроенный в параметры varadic T..., где это возможно. CValListPointer следует использовать только тогда, когда вам нужно взаимодействовать с API-интерфейсами Objective C и C, которые принимают аргументы va_list.