В чем различие и варианты использования-ва списка, CVaListPointer, какой-либо объект ..., CVarArgType?


Вопрос

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

Nota bene

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

Фон

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

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

NSPredicate-инициализаторы

Заголовочный файл 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]
    */

Редактировать:

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

argumentArray-док

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

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

1 ответ:

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

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

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

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