Полный список директив компилятора Objective-C 2.0

Очень сложно найти полный список директив компилятора Objective-C в одном месте. Всем конечно известны @interface, @implementation, но есть и такие, как @dynamic и @encode которые встречают гораздо реже, и зачастую понимаются неправильно.

Вот их полный список, разъяснения приводятся под катом:

  • @class
  • @protocol @required @optional @end
  • @interface @public @package @protected @private @property @end
  • @implementation @synthesize @dynamic @end
  • @throw @try @catch @finally
  • @synchronized @autoreleasepool
  • @selector @encode
  • @compatibility_alias
  • @«string»



@class


Используется для предварительного объявления класса. При использовании этой директивы класс помечается как известный, даже без загрузки заголовочного файла.


@class ClassName


Однако, в отличии от @protocol и @selector вы не можете написать следующее для получения класса по имени


// ОШИБКА: это работать не будет!
Class c = @class( ClassName );


используйте вместо этого


Class c = [ ClassName class ];


@protocol @required @optional @end


Директивы используются для объявления протокола. Кроме того, протокол может адаптировать другие протоколы.


@protocol ProtocolName < aProtocol, anotherProtocol >
@required
  // объявление сообщений
@optional
  // объявление сообщений
@end


Также как и в случае с @selector вы можете использовать @protocol для получения объекта по имени:


-( void ) aMethod
{
  Protocol* aProtocol = @protocol( ProtocolName );
}


Зависимые директивы

  • @requred (используется по-умолчанию) — Определяет методы, которые следуют после @required как обязательные.
  • @optional — Определяет методы, которые следуют после @optional как необязательные. Классы, которые адаптируют протокол, могут сами решать — реализовывать эти методы или нет. Классы, которые используют необязательные методы протокола, должны делать проверку на существование. Например:

    
    [ object respondsToSelector: @selector( optionalProtocolMethod ) ];
    
  • @end — определяет завершение объявления протокола

@interface @public @package @protected @private @property @end


@interface — определяет начало объявления класса или категории.

Объявление класса

Класс предок может не объявляться, однако, все классы Objective-C должны напрямую или косвенно наследоваться от NSObject. Директива @interface может определять также, что класс адаптирует определенные протоколы:


@interface ClassName : SuperClassName < aProtocol, anotherProtocol >
{
@public
  // переменные экземпляра
@package 
  // переменные экземпляра
@protected
  // переменные экземпляра
@private
  // переменные экземпляра
}

// объявление свойств
@property ( atomic, readwrite, assign ) id aProperty;

// публичные методы класса и экземпляров
@end


Объявление категории

Директива @interface для категорий не может добавлять переменных экземпляра. Однако, она может определять, что категория адаптирует дополнительные протоколы. Имя категории может быть опущено (остаются только круглые скобки), если категория добавляется в файл реализации для добавления частных методов класса.


@interface ClassName ( CategoryName ) < aProtocol, anotherProtocol >

// объявление свойств
@property ( nonatomic, retain ) NSString* stringProperty;

// объявление методов
@end


Зависимые директивы

  • @public — Определяет, что переменные экземпляра, следующие за директивой будут доступны публично. Публичные переменные могут быть прочтены и изменены с помощью следующей конструкции:
    
    someObject->aPublicVariable = 10;
    
  • @package — Определяет, что переменные экземпляра, следующие за директивой будут публично доступны в библиотеке, которая определяет класс, но закрытыми за пределами этой библиотеки. Важное замечание, это справедливо только для 64-разрядных систем. На 32-разрядных системах имеет то же значение, что и @public
  • @protected (по умолчанию) — Определяет, что переменные экземпляра, следующие за директивой, будут доступны только для класса и его потомков.
  • @private — Определяет, что переменные экземпляра, следующие за директивой, будут доступны только в пределах данного класса
  • @property — Определяет свойство, которое может быть использовано с помощью точечной нотации. За директивой @property могут следовать необязательные круглые скобки, которые содержат дополнительные ключевые слова, которые определяют поведение свойства. Вот они:
    • readwrite (по-умолчанию) и readonly — генерируются одновременно сеттеры и геттеры (setters/getters) или только геттеры
    • assign (по-умолчанию) и retain, copy — применяются только для свойств, которые могут быть безопасно приведены к id. Assign — просто присваивает переданное значение. Retain — посылает release текущему значению переменной экземпляра, потом посылает retain новому объекту, и присваивает новое значение переменной экземпляра. Copy — посылает release текущему значению переменной экземпляра, затем copy новому объекту и присваивает новый объект переменной экземпляра. В последних двух случаях, вы должны послать release (или присвоить nil) свойству при dealloc.
    • atomic, (по-умолчанию) и nonatomic — свойства с ключевым словом atmoic — потокобезопасны, с nonatomic — могут быть проблемы при многопоточном доступе. Доступ к nonatomic свойствам обычно быстрее чем к atomic, поэтому они часто используются в однопоточных приложениях.
    • weak (по-умолчанию) и strong — доступны, если включен автоматический подсчет ссылок (Automatic Reference Counting — ARC). В этом случае strong — это синоним для retain, в то время как weak — assign, с одним лишь исключением, что свойство с weak автоматически устанавливается в nil когда объект уничтожается. Также следует учитывать, что ключ weak доступен только начиная с iOS 5 и Mac OS X 10.7 (Lion).
  • @end — Определяет завершение объявления класса или категории

@implementation @synthesize @dynamic @end


Директива @implementation определяет начало определения (реализации) класса или категории.

Определение класса


@implementation ClassName

@synthesize aProperty, bProperty;
@synthesize cProperty=instanceVariableName;

@dynamic anotherProperty;

// определение методов
@end


Определение категории


@implementation ClassName ( CategoryName )

@synthesize aProperty, bProperty;
@synthesize cProperty=instanceVariableName;

@dynamic anotherProperty, bnotherProperty;

// определение методов
@end


Зависимые директивы

  • @synthesize — дает указание компилятору, что необходимо автоматически сгенерировать сеттеры и геттеры для данных (разделенных запятой) свойств. Сеттеры и геттеры автоматически создаются согласно указанным в объявлении свойства директивам. Если переменные экземпляра называются не так, как указано после директивы @property, вы можете соединить их с помощью знака равенства
  • @dynamic — сообщает компилятору, что требуемые сеттеры и геттеры для данных свойств будут реализованы вручную или динамически во время выполнения. При доступе к таким свойствам, компилятор не будет выдавать предупреждений, даже если требуемые сеттеры и геттеры не реализованы. Вы можете использовать такие свойства, когда хотите, чтобы сеттеры и геттеры выполняли какой-то специфичный для вас код.
  • @end — указывает на завершение определения класса или категории

@throw @try @catch @finally


Директивы используются для обработки исключений

Посылка и обработка исключений


@try
{
  // код, который может кинуть исключение ... как например
  NSException* exception = 
    [ NSException exceptionWithName: @"ExampleException"
                             reason: @"In your face!"
                           userInfo: nil ];
  @throw exception;
}
@catch ( CustomException* ce )
{
  // код обработки определенного исключения
}
@catch ( NSException* ne )
{
  // код обработки всех остальных исключений

  // чтобы просто пробросить исключение дальше
  @throw ;
}
@finally
{
  // код, который выполнится всегда после обработки, несмотря на то
  // было исключение или нет
}


@synchronized


Заключает блок кода в мьютекс. Обеспечивает гарантию того, что блок кода и объект блокировки будут доступны только из одного потока в момент времени.


-( void ) aMethodWithObject: ( id )object
{
  @synchronized( object )
  {
    // код, который работает с объектом блокировки
  }
}


@autoreleasepool


В тех приложения, в которых вы используете автоматический подсчет ссылок (ARC), вы должны использовать @autoreleasepool как замену для NSAutoreleasePool. И вообще, @autoreleasepool примерно в 6 раз быстрее, чем NSAutoreleasePool, поэтому Apple рекомендует использовать его даже для не-ARC приложений.

Кроме того, вы не должны определять переменную внутри блока @autoreleasepool и затем продолжать использовать ее после. Подобный код должен быть исключен.

Пример использования:


-( void ) aMethod
{
  @autoreleasepool
  {
    // код, который создает большое количество временных объектов
  }
}


@selector


Возвращает специальный тип селекторов SEL выбранного метода Objective-C. Генерирует предупреждение компилятора, если метода не объявлен или не существует.


-( void ) aMethod
{
  SEL aMethodSelector = @selector( aMethod );
  [ self performSelector: aMethodSelector ];
}


@encode


Возвращает кодировку типа.


-( void ) aMethod
{
  char* enc1 = @encode( int );                   // enc1 = "i"
  char* enc2 = @encode( id );                    // enc2 = "@"
  char* enc3 = @encode( @selector( aMethod ) );  // enc3 = ":"

  // практический пример
  CGRect rect = CGRectMake( 0, 0, 100, 100 );
  NSValue* v = [ NSValue value: &rect withObjCType: @encode( CGRect ) ];
}


@compatibility_alias


Позволяет вам задать псевдоним для существующего класса. Первый параметр — имя псевдонима для имени класса, класса с таким именем не должно существовать. Второй параметр — имя существующего класса, для которого создается псевдоним.


@compatibility_alias AliasClassName ExistingClassName


После этого, вы можете использовать AliasClassName вместо ExistingClassName. Это может быть полезно после переименования класса без изменения его поведения. Вы можете использовать @compatibility_alias для того, чтобы не делать много изменений в существующем коде.

@«string»


Объявляет константный объект класса NSString. Для таких строк не требуется вызывать retain или release.


-( void ) aMethod
{
  NSString* str = @"This is a constant string.";
  NSUInteger strLength = [ @"This is legal!" length ];
}


Заключение


Я надеюсь, что вам понравился этот список, и он будет полезен вам. Если есть какие-то директивы, которых нет в списке, пожалуйста опишите их в комментариях к статье. Буду очень благодарен.

По мотивам тут.


Похожие записи




Комментарии (0)

Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.