Objective-C Language
Основные типы данных
Поиск…
Синтаксис
- BOOL havePlutonium = YES; // Прямая привязка
- BOOL fastEnough = (car.speedInMPH> = 88); // Выражение сравнения
- BOOL fluxCapacitorActive = (hasPlutonium && fastEnough); // Булево выражение
- id somethingWicked = [witchesCupboard lastObject]; // Получить нетипизированный объект
- id powder = prepareWickedIngredient (somethingWicked); // Пропускаем и возвращаем
- if ([component isKindOfClass: [Toad class]]) {// Тестируем тип среды выполнения
BOOL
Тип BOOL
используется для логических значений в Objective-C. Он имеет два значения: YES
и NO
, в отличие от более обычных «истинных» и «ложных».
Его поведение прост и идентично языку C.
BOOL areEqual = (1 == 1); // areEqual is YES
BOOL areNotEqual = !areEqual // areNotEqual is NO
NSCAssert(areEqual, "Mathematics is a lie"); // Assertion passes
BOOL shouldFlatterReader = YES;
if (shouldFlatterReader) {
NSLog(@"Only the very smartest programmers read this kind of material.");
}
BOOL
является примитивным, поэтому его нельзя хранить непосредственно в коллекции Foundation. Он должен быть завернут в NSNumber
. Кланг предоставляет специальный синтаксис для этого:
NSNumber * yes = @YES; // Equivalent to [NSNumber numberWithBool:YES]
NSNumber * no = @NO; // Equivalent to [NSNumber numberWithBool:NO]
Реализация BOOL
напрямую основана на C, поскольку она является типизированным стандартным типом bool
типа C99. Значения YES
и NO
определены как __objc_yes
и __objc_no
, соответственно. Эти специальные значения являются встроенными компиляторами, введенными Clang, которые переведены на (BOOL)1
и (BOOL)0
. Если они недоступны, YES
и NO
определяются непосредственно как форма целого числа. Определения содержатся в заголовке времени Objective-C objc.h
Я бы
id
- общий указатель объекта, тип Objective-C, представляющий «любой объект». Экземпляр любого класса Objective-C может быть сохранен в переменной id
. id
и любой другой тип класса можно назначать туда и обратно без кастинга:
id anonymousSurname = @"Doe";
NSString * surname = anonymousSurname;
id anonymousFullName = [NSString stringWithFormat:@"%@, John", surname];
Это становится актуальным при извлечении объектов из коллекции. Возвращаемые типы методов, таких как objectAtIndex:
являются id
именно по этой причине.
DataRecord * record = [records objectAtIndex:anIndex];
Это также означает, что параметр метода или функции, введенный как id
может принимать любой объект.
Когда объект вводится как id
, любое известное сообщение может быть передано ему: отправка метода не зависит от типа времени компиляции.
NSString * extinctBirdMaybe =
[anonymousSurname stringByAppendingString:anonymousSurname];
Разумеется, сообщение, на которое объект фактически не отвечает, все равно вызовет исключение во время выполнения.
NSDate * nope = [anonymousSurname addTimeInterval:10];
// Raises "Does not respond to selector" exception
Защита от исключения.
NSDate * nope;
if([anonymousSurname isKindOfClass:[NSDate class]]){
nope = [anonymousSurname addTimeInterval:10];
}
Тип id
определяется в objc.h
typedef struct objc_object {
Class isa;
} *id;
SEL
Селекторы используются как идентификаторы методов в Objective-C.
В приведенном ниже примере есть два селектора. new
и setName:
Person* customer = [Person new];
[customer setName:@"John Doe"];
Каждая пара скобок соответствует отправке сообщения. В первой строке мы отправляем сообщение, содержащее new
селектор, в класс Person
а во второй строке мы отправляем сообщение, содержащее селектор setName:
и строку. Приемник этих сообщений использует селектор для поиска правильного действия для выполнения.
В большинстве случаев достаточно передавать сообщения, используя синтаксис скобки, но иногда вам приходится работать с самим селектором. В этих случаях тип SEL
может использоваться для ссылки на селектор.
Если селектор доступен во время компиляции, вы можете использовать @selector()
чтобы получить ссылку на него.
SEL s = @selector(setName:);
И если вам нужно найти селектор во время выполнения, используйте NSSelectorFromString.
SEL s NSSelectorFromString(@"setName:");
При использовании NSSelectorFromString не забудьте обернуть имя селектора в NSString.
Он обычно используется для проверки того, реализует ли делегат необязательный метод.
if ([self.myDelegate respondsToSelector:@selector(doSomething)]) {
[self.myDelegate doSomething];
}
IMP (указатель реализации)
IMP - это тип C, относящийся к реализации метода, также известный как указатель реализации. Это указатель на начало реализации метода.
Синтаксис:
id (*IMP)(id, SEL, …)
IMP определяется:
typedef id (*IMP)(id self,SEL _cmd,…);
Для доступа к этому IMP можно использовать сообщение «methodForSelector» .
Пример 1:
IMP ImpDoSomething = [myObject methodForSelector:@selector(doSomething)];
Метод, адресованный IMP, может быть вызван разыменованием IMP.
ImpDoSomething(myObject, @selector(doSomething));
Таким образом, эти призывы равны:
myImpDoSomething(myObject, @selector(doSomething));
[myObject doSomething]
[myObject performSelector:mySelector]
[myObject performSelector:@selector(doSomething)]
[myObject performSelector:NSSelectorFromString(@"doSomething")];
Пример: 2:
SEL otherWaySelector = NSSelectorFromString(@“methodWithFirst:andSecond:andThird:");
IMP methodImplementation = [self methodForSelector:otherWaySelector];
result = methodImplementation( self,
betterWaySelector,
first,
second,
third );
NSLog(@"methodForSelector : %@", result);
Здесь мы вызываем [NSObject methodForSelector, который возвращает нам указатель на функцию C, которая фактически реализует метод, который мы можем впоследствии вызвать напрямую.
NSInteger и NSUInteger
NSInteger - это просто typedef для int или long в зависимости от архитектуры. То же самое касается NSUInteger, который является typedef для неподписанных вариантов. Если вы проверите NSInteger, вы увидите следующее:
#if __LP64__ || (TARGET_OS_EMBEDDED && !TARGET_OS_IPHONE) || TARGET_OS_WIN32 || NS_BUILD_32_LIKE_64
typedef long NSInteger;
typedef unsigned long NSUInteger;
#else
typedef int NSInteger;
typedef unsigned int NSUInteger;
#endif
Разница между подписанным и unsigned int или long заключается в том, что подписанный int или long может содержать отрицательные значения. Диапазон int равен -2 147 483 648 до 2 147 483 647, тогда как unsigned int имеет диапазон от 0 до 4 294 967 295. Значение удваивается, потому что первый бит больше не используется, чтобы сказать, что значение отрицательное или нет. Для длинного и NSInteger на 64-битных архитектурах диапазон намного шире.
Большинство методов, предоставляемых Apple, возвращают целое число NS (U) по нормальному int. Вы получите предупреждение, если попытаетесь применить его к нормальному int, потому что вы потеряете точность, если работаете в 64-битной архитектуре. Не то, чтобы это было важно в большинстве случаев, но проще использовать NS (U) Integer. Например, метод count в массиве вернет NSUInteger.
NSNumber *iAmNumber = @0;
NSInteger iAmSigned = [iAmNumber integerValue];
NSUInteger iAmUnsigned = [iAmNumber unsignedIntegerValue];
NSLog(@"%ld", iAmSigned); // The way to print a NSInteger.
NSLog(@"%lu", iAmUnsigned); // The way to print a NSUInteger.
Подобно BOOL, NS (U) Integer является примитивным типом данных, поэтому иногда вам нужно обернуть его в NSNumber, который вы можете использовать @ перед целым, чтобы отличать его, как указано выше, и извлекать его, используя приведенные ниже методы. Но чтобы передать его NSNumber, вы также можете использовать следующие методы:
[NSNumber numberWithInteger:0];
[NSNumber numberWithUnsignedInteger:0];