Общественная сфера в Objective-C? - PullRequest
5 голосов
/ 29 июня 2009

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

Как мне объявить Ivar, чтобы он был доступен из ВСЕХ классов в проекте?

[Не знаю, имеет ли это значение, но рассматриваемый ивар является (экземпляром) моего класса Model, данные которого должны быть доступны для различных контроллеров представления.]

Насколько я могу судить из "Область действия переменных экземпляра" в Язык программирования Objective-C 2.0 ... это можно сделать с помощью директивы @public.

Итак, я попробовал это в блоке @interface, где объявлен ivar:

@interface ...

...

@public
ModelClass *theModel;

@end

... Но когда я пытаюсь сослаться на «theModel» в другом классе, компилятор не выполняет автозаполнение, и когда я его в любом случае набираю, компилятор показывает: «Ошибка:« theModel »не объявлена ​​(первое использование в этой функции)».

Я предполагаю, что это вопрос Сфера, и что я не сделал доступным ивару соответственно, но как? Каким-то образом мне нужно получить к нему доступ или каким-то образом сделать его указатель доступным.

Любые идеи будут ОЧЕНЬ высоко оценены. Большое спасибо!

Ответы [ 6 ]

5 голосов
/ 29 июня 2009

Возможно, вы забыли поместить переменную экземпляра в фигурные скобки класса, куда идут все объявления переменных экземпляра?

@interface Foo : NSObject {

    // other instance variable declarations

    @public
    ModelClass *theModel;
}

// method and property declarations

@end

Кроме того, можете ли вы показать нам код того, как вы пытаетесь получить доступ к переменной экземпляра из другого места? Правильный синтаксис должен быть:

myFooInstance->theModel

, где myFooInstance - это значение типа "Foo *"

3 голосов
/ 29 июня 2009

Я делаю свойства доступными для всех представлений, управляемых панелью вкладок через синглтон, представляющий мою модель данных. Это эффективно и позволяет всем представлениям обращаться к данным (а также к любым другим элементам приложения. Создать синглтон просто (имеется множество примеров для SO). Вы просто запрашиваете экземпляр и получаете нужные значения свойств.

Вот рамки для создания Singleton. Ключевыми моментами являются статический экземпляр и тот факт, что вы выполняете инициализацию как [[self alloc] init];. Это обеспечит правильную очистку объекта. Все методы в нижней части класса являются стандартными из документов SDK, чтобы гарантировать, что вызовы выпуска игнорируются (поскольку объект используется глобально).

Одноэлементный котел (ApplicationSettings.m):

static ApplicationSettings *sharedApplicationSettings = nil;

+ (ApplicationSettings*) getSharedApplicationSettings
{
    @synchronized(self) {
        if (sharedApplicationSettings == nil) {
            [[self alloc] init]; // assignment not done here
        }
    }
    return sharedApplicationSettings;
}

+ (id)allocWithZone:(NSZone *)zone
{
    @synchronized(self) {
        if (sharedApplicationSettings == nil) {
            sharedApplicationSettings = [super allocWithZone:zone];
            return sharedApplicationSettings;  // assignment and return on first allocation
        }
    }
    return nil; //on subsequent allocation attempts return nil
}

- (id)copyWithZone:(NSZone *)zone
{
    return self;
}

- (id)retain
{
    return self;
}

- (unsigned)retainCount
{
    return UINT_MAX;  //denotes an object that cannot be released
} 

- (void)release
{
    //do nothing
}

- (id)autorelease
{
    return self;
}
3 голосов
/ 29 июня 2009

Вы не можете получить доступ к iVars из любого другого класса.

Вы должны объявить метод получения / установки для изменения или просмотра переменной из другого класса - на самом деле вы ищете свойства, которые облегчают определение и доступ к этим методам получения / установки.

В приведенном выше примере у вас будет свойство, определенное сразу после блока, который определяет локальную переменную в заголовочном файле:

@property (nonatomic, retain) ModelClass *theModel;

В файле реализации вы получите getter / setter, созданный с помощью оператора @synthesize сразу после строки @implementation:

@synthesize theModel;

Тогда, если у вас есть экземпляр вашего класса, вы получите доступ к переменной экземпляра класса следующим образом:

myInstance.theModel = [[[ModelClass alloc] init] autorelease];

Причина @public & @private заключается в том, чтобы определить видимость для подклассов (которые, будучи расширениями этого типа класса, также получают все локальные переменные класса, определенные суперклассом), а не для любого случайного класса.

1 голос
/ 29 июня 2009

Стандартный способ Objective-C состоит в том, чтобы иметь метод класса, который возвращает ivar

В вашем .h файле:

+ (id)defaultModel;

и в вашем .m файле:

static ModelClass * defaultModelInstance;

@implementation ModelClass

+ (id)defaultModel {
    if (!defaultModelInstance) {
        defaultModelInstance = [[ModelClass alloc] init];
    }
    return defaultModelInstance;
}

@end

хотя для этого потребуется настроить, если вам нужен определенный ивар, а не просто "ивар, который всегда одинаков"

этот тип дизайна используется многими классами Какао, т.е. [NSWorkspace sharedWorkspace]

0 голосов
/ 30 июня 2009

СПАСИБО ВСЕМ за очень полезную дискуссию на эту тему! Очевидно, что есть несколько способов приблизиться к этому, так что это очень полезный набор методов.


Просто чтобы вы знали, что при дальнейшем изучении этой проблемы я наткнулся на пару других очень полезных страниц, перечисленных ниже. Они включают упоминание NSNotificationCenter, о котором я раньше не слышал; а также идея шаблона проектирования «внедрение зависимостей».

Идея состоит в том, чтобы поддерживать "низкую связь" (1) между классами, делая код более модульным и более удобным для модульного тестирования.

И хотя шаблон «уведомления» звучит как отличная идея, в этом случае он может быть немного излишним, учитывая, что мне нужен только ОДИН экземпляр модели данных во время работы приложения, и он не меняется во всем.

Наконец, несмотря на то, что директива компилятора "@public" хорошо документирована в руководстве Apple Obj-C (2), позже я обнаружил захватывающий эдикт в другом документе, утверждающий, что он не должен использоваться ! Цитируется из собственного Основы какао Apple (3):
«Дайте правильную область видимости вашим переменным экземпляра. Никогда не определяйте область видимости переменной как @public, так как это нарушает принцип инкапсуляции. ...»
(Странно, что они не упоминают об этом в своем руководстве «Objective-C 2.0», где директива фактически объясняется.)

Во всяком случае, вот еще пара ссылок, которые, как я обнаружил, полны некоторых замечательных идей. FYI:

  • С.О .: "Какой самый лучший способ общаться между viewcontrollers? " (4) << </p>

  • CocoaWithLove: "Пять подходов к прослушивание, наблюдение и уведомление в Какао " (5)

  • CocoaWithLove: "Одиночки, AppDelegates и данные верхнего уровня " (6)


Надеюсь, что это поможет. В любом случае, спасибо всем еще раз!

Лучший, Rond

P.S. Хлоп! Это не позволит мне публиковать более одной встроенной гиперссылки, поэтому я перечислю их здесь. Очевидно, все они имеют префикс «http://” ...: O

(1): en.wikipedia.org/wiki/Coupling_(computer_science)
(2): developer.apple.com/DOCUMENTATION/Cocoa/Conceptual/ObjectiveC/Articles/ocDefiningClasses.html#//apple%5Fref/doc/uid/TP30001163-CH12-TPXREF127
(3): developer.apple.com/documentation/Cocoa/Conceptual/CocoaFundamentals/AddingBehaviortoaCocoaProgram/AddingBehaviorCocoa.html#//apple_ref/doc/uid/TP40002974-CH5-SW12
(4): stackoverflow.com/questions/569940/whats-the-best-way-to-communicate-between-viewcontrollers
(5): cocoawithlove.com/2008/06/five-approaches-to-listening-observing.html
(6): cocoawithlove.com/2008/11/singletons-appdelegates-and-top-level.html

0 голосов
/ 29 июня 2009

Подумайте о глобальной переменной C.

Добавление:
extern ModelClass* theModel;
после @end в заголовке сделает переменную видимой везде, где вы включаете заголовок.

В файле ModelClass.cpp добавить:
ModelClass* theModel;
до реализации класса.

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

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