Используя значения
NSValue
объект является простым контейнером для единственного C или элемента данных Objective C. Это может содержать любой из скалярных типов такой как int
, float
, и char
, а также указатели, структуры и объект id
s. Цель этого класса состоит в том, чтобы позволить элементам таких типов данных быть добавленными к объектам коллекции, таким как экземпляры NSArray
или NSSet
, которые требуют, чтобы их элементы были объектами. NSValue
объекты являются всегда неизменными.
Создать NSValue
объект с определенным элементом данных, Вы обеспечиваете указатель на элемент вместе со струной до, описывающей тип элемента в кодировании типа Objective C. Вы получаете эту строку с помощью @encode()
директива компилятора, возвращающая специфичное для платформы кодирование для данного типа (см. Кодировки Типа для получения дополнительной информации о @encode()
и список кодов типа). Например, эта выборка кода создает theValue, содержащий NSRange
:
NSRange myRange = {4, 10}; |
NSValue *theValue = [NSValue valueWithBytes:&myRange objCType:@encode(NSRange)]; |
Следующий пример иллюстрирует кодирование пользовательской структуры C.
// assume ImaginaryNumber defined: |
typedef struct { |
float real; |
float imaginary; |
} ImaginaryNumber; |
ImaginaryNumber miNumber; |
miNumber.real = 1.1; |
miNumber.imaginary = 1.41; |
NSValue *miValue = [NSValue valueWithBytes: &miNumber |
withObjCType:@encode(ImaginaryNumber)]; |
ImaginaryNumber miNumber2; |
[miValue getValue:&miNumber2]; |
Тип, который Вы указываете, должен иметь постоянную длину. Вы не можете сохранить струны до, массивы переменной длины и структуры и другие типы данных неопределенной длины в NSValue
— необходимо использовать NSString
или NSData
объекты для этих типов. Можно сохранить указатель на элемент переменной длины в NSValue
объект. Следующая выборка кода неправильно пытается поместить струну до непосредственно в NSValue
объект:
/* INCORRECT! */ |
char *myCString = "This is a string."; |
NSValue *theValue = [NSValue valueWithBytes:myCString withObjCType:@encode(char *)]; |
В этой выборке кода содержание myCString интерпретируется как указатель на a char
, таким образом, первые четыре байта, содержавшиеся в строке, обрабатываются как указатель (фактическое число используемых байтов может меняться в зависимости от аппаратной архитектуры). Т.е. последовательность, «Это» интерпретируется как значение указателя, которое вряд ли будет юридическим адресом. Корректный способ сохранить такой элемент данных состоит в том, чтобы использовать NSString
объект (если необходимо содержать символы в объекте), или передать адрес его указателя, не самого указателя:
/* Correct. */ |
char *myCString = "This is a string."; |
NSValue *theValue = [NSValue valueWithBytes:&myCString withObjCType:@encode(char **)]; |
Здесь адрес myCString передается (&myCString), таким образом, адрес первого символа строки сохранен в theValue.