Как я могу решить эту проблему с двунаправленными зависимостями в классах Objective-C? - PullRequest
4 голосов
/ 07 мая 2009

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

У меня есть ClassA, который создаст дочерний объект из ClassB и назначит его переменной экземпляра. Подробно: ClassA выделит и инициализирует ClassB в назначенном инициализаторе и назначит его переменной экземпляра childObject. Заголовок выглядит так:

#import <Foundation/Foundation.h>
#import "ClassB.h"

@interface ClassA : NSObject {
    ClassB *childObject;
}

@end

Затем есть заголовок ClassB. ClassB должен иметь ссылку на ClassA.

#import <Foundation/Foundation.h>
#import "ClassA.h"

@interface ClassB : NSObject {
    ClassA *parentObject;
}

- (id)initWithClassA:(ClassA*)newParentObject;

@end

Когда объект ClassA создает дочерний объект из ClassB, тогда объект ClassA вызывает назначенный инициализатор объекта ClassB, где он должен передать себя (self).

Я чувствую, что что-то не так, но сейчас я не совсем понимаю, что это такое. Я думаю, я знаю, что это не работает. Они не могут предложить импорт друг друга. Компилятор просто говорит мне: «ошибка: синтаксическая ошибка перед« ClassA »». Когда я удаляю оператор импорта для импорта ClassA, удаляю переменную экземпляра parentAbject ClassA * и удаляю инициализатор обозначений (который принимает ссылку ClassA), тогда он работает.

Теперь вот что я хочу достичь (если это имеет значение): мне нужно очень особенное и сложное поведение в UIScrollView. Поэтому я решил подкласс его. Поскольку основная часть будет выполняться внутри методов делегата, я решил создать «универсальный» объект делегата для моего подкласса UIScrollView. Мой подкласс UIScrollView автоматически создает этот специальный объект делегата и назначает его свойству делегата. Самому объекту делегата нужна ссылка на его родителя, настроенный UIScrollView, чтобы он имел доступ к подпредставлениям этого представления прокрутки. Но в любом случае, даже если есть лучший способ решить эту проблему, я все равно хотел бы знать, как я могу сделать это таким образом с двумя «взаимозависимыми» объектами, которые нуждаются друг в друге.

Любые предложения приветствуются!

Ответы [ 3 ]

15 голосов
/ 07 мая 2009

Вам не нужно импортировать эти классы в заголовочные файлы. Используйте @class в заголовочных файлах, а затем используйте #import только в .m файлах:

// ClassA.h:
@class ClassB;
@interface ClassA : NSObject
{
    ClassB *childObject;
}
@end


// ClassA.m:
#import "ClassA.h"
#import "ClassB.h"
@implementation ClassA
//..
@end


// ClassB.h
@class ClassA;
@interface ClassB : NSObject
{
    ClassA *parentObject;
}
- (id)initWithClassA:(ClassA*)newParentObject;
@end


// ClassB.m:
#import "ClassB.h"
#import "ClassA.h"
@implementation ClassB
//..
@end
5 голосов
/ 07 мая 2009

Что вам нужно сделать, это «объявить вперед» ваши классы, а не импортировать полное определение. Например:

#import <Foundation/Foundation.h>

@class ClassB; // Tell the compiler that ClassB exists

@interface ClassA : NSObject {
    ClassB *childObject;
}

@end

И вы делаете нечто подобное для заголовочного файла ClassB.

5 голосов
/ 07 мая 2009

Используйте @class A; и @class B; вместо #import s, чтобы сообщить компилятору не беспокоиться об определении класса, а просто продолжать, потому что он встретится с ними позже.

Замените #import "A.h" на @class A;.

.
...