С каких это пор можно объявлять свойства Objective-C 2.0 в категории? - PullRequest
14 голосов
/ 27 декабря 2010

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

Я пошел на SO и Google, чтобы попытаться объяснить ему, что нет, категории Objective-C могут использоваться только для добавления методов, но не свойств. Я нашел такие вопросы, как:

Но потом я нашел эту ссылку на сайте Apple, которая содержит следующее о объявлении @property:

Объявление свойства начинается с ключевое слово @property. @property может появляются в любом месте метода список объявлений найден в @ интерфейс класса. @property банка также появляются в декларации протокол или категория . (выделение добавлено)

Я знаю, что это не работает:

@interface MyClass ()
NSInteger foobar;
- (void) someCategorizedMethod;
@end

Но это компилируется:

@interface MyClass ()
@property NSInteger foobar;
- (void) someCategorizedMethod;
@end

Мой вопрос: а) какая здесь самая лучшая практика? и (b) является ли это чем-то новым для Objective-C 2.0, и вместо того, чтобы использовать «реальный» iVar, он просто использует ассоциативное хранение за кулисами, чтобы заставить это работать?

Ответы [ 3 ]

31 голосов
/ 27 декабря 2010

Вы всегда могли объявить @property в категории.То, что вы не могли сделать - и все еще не можете - это объявить хранилище для свойства в категории, ни в качестве переменной экземпляра, ни через `@synthesize.

Однако ....

@interface MyClass () - это , а не категория .Это расширение класса и имеет явно более специфическую роль, чем категория.

А именно, расширение класса может использоваться для расширения @ interface класса, и это включает в себя @properties, которые могутбыть @synthesized (включая синтезирование хранилища в современной среде выполнения).

Foo.h:

@interface Foo
@end

Foo.m:

@interface Foo()
@property int x;
@end

@implementation Foo
@synthesize x; // synthesizes methods & storage
@end

он просто использует ассоциативное хранилище за кулисами, чтобы сделать эту работу?

Нет -это реальная переменная экземпляра.Современная среда выполнения устраняет проблему хрупкого базового класса.

@interface MyClass ()
NSInteger foobar;
- (void) someCategorizedMethod;
@end

Выше не работает (как и ожидалось), потому что foobar, по сути, является глобальной переменной.

Если вы измените его на:

@interface MyClass () {
    NSInteger foobar;
}
- (void) someCategorizedMethod;
@end

Тогдаон будет работать с последней версией компилятора llvm (с правильными флагами, как указано @Joshua в комментарии).

1 голос
/ 13 сентября 2012

Ассоциированное хранение является решением.Взгляните на этот пост .

1 голос
/ 27 декабря 2010

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

Вещи начинают усложняться, если автоматически создается ивар, как это возможно в некоторых конфигурациях.

Главное здесь то,объявление ивара не зависит от собственности.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...