В файле интерфейса: когда использовать форвардное объявление для пользовательского класса, а не только его заголовок?

У меня есть подкласс UIViewController называемый FullScreenViewController который имеет свойство типа ImageScrollView которое является подклассом объекта UIScrollView . Реализация и интерфейс выглядят следующим образом:

FullScreenViewController.h

 #import <UIKit/UIKit.h> @class ImageScrollView; @interface FullScreenViewController : UIViewController { ImageScrollView *_scrollView; } @property(nonatomic, retain) ImageScrollView *scrollView; @end 

FullScreenViewController.m

 #import "FullScreenViewController.h" #import "ImageScrollView.h" @implementation FullScreenViewController @synthesize scrollView = _scrollView; ... @end 

теперь я подкласс FullScreenViewController , и я пытаюсь получить доступ к любым свойствам из свойства ImageScrollView и я продолжаю получать сообщение об ошибке: «Свойство не может быть найдено». Когда я добавляю ImageScrollView.h в подкласс, он работает, но я не понимаю этого. Я уже добавил ImageScrollView.h в FullScreenViewController , почему я должен добавить его снова?

UPDATE: вместо использования объявления прямого класса я включил ImageScrollView.h в FullScreenViewController.h. Я немного смущен, почему я когда-либо использовал форвардную декларацию, а не только файл .h?

Учитывая заголовок:

 @interface FullScreenViewController : UIViewController { ImageScrollView *_scrollView; } @property(nonatomic, retain) ImageScrollView *scrollView; @end 

для этого требуется форвардная декларация @class ImageScrollView . Это говорит компилятору, что существует класс ImageScrollView именем ImageScrollView .

Конечно, с объявлением вперед интерфейс не отображается там, где вам нужно его использовать, кроме тех случаев, когда вы также #import ImageScrollView, где вы его используете.

теперь я подкласс FullScreenViewController, и я пытаюсь получить доступ к любым свойствам из свойства ImageScrollView, и я продолжаю получать сообщение об ошибке: «Свойство не может быть найдено». Когда я добавляю ImageScrollView.h в подкласс, он работает, но я не понимаю этого. Я уже добавил ImageScrollView.h в FullScreenViewController, почему я должен добавить его снова?

ImageScrollView не отображается в подклассе FullScreenViewControllerSubclass . ImageScrollView.h видна только там, где #import ed. FullScreenViewController.m не отображается в FullScreenViewControllerSubclass.m . Поэтому вы должны написать другой #import в FullScreenViewControllerSubclass.m чтобы использовать ImageScrollView там.

UPDATE: вместо использования объявления прямого класса я включил ImageScrollView.h в FullScreenViewController.h. Я немного смущен, почему я когда-либо использовал форвардную декларацию, а не только файл .h?

Используйте forwards для быстрого времени сборки и разумных, контролируемых структур зависимостей. Это очень трудоемкая проблема для отмены. И эта проблема становится намного хуже по мере увеличения размеров ваших программ и библиотек:

Вы предпочли бы изменение заголовка в проекте среднего размера, чтобы потребовать перекомпиляцию 50 источников со средним предварительно обработанным вводом 150 000 строк на перевод, или вы бы предпочли, чтобы это изменение повлияло на 6 источников со средним предварительно обработанным вводом 40 000 строк на перевод ? Разница здесь заключается в том, что небольшое изменение требует инкрементного перестроения от секунд до минут, в зависимости от того, как вы структурировали свои зависимости и импорт.

Причина, по которой вам нужно добавить его, – это только объявление @class в файле FullScreenViewController.h. Это только объявляет переменную типа ImageScrollView * как указатели на объект класса ImageScrollView. Это не дает вам доступ к свойствам ImageScrollView. Чтобы получить доступ к методам и свойствам, характерным для ImageScrollView, вам необходимо включить объявление @interface в ImageScrollView, которое, как я полагаю, содержится в файле ImageScrollView.h.

Вы пытались получить доступ к нему, используя псевдоним _scrollView или scrollView. Вы должны получить к нему доступ с помощью _scrollView и посмотреть, не импортировал ли файл в .m или .h, поскольку @class не хватит.