Джон дает хороший совет, но здесь немного больше информации о причинах, причинах и исключениях.
Существует две цели, позволяющие избежать импорта заголовков в заголовки: улучшенное время инкрементной сборки и предотвращение циклических зависимостей. Если вы импортируете A.h
в B.h
и импортируете B.h
в C.h
, то каждый раз, когда вы что-либо изменяете в A.h
, вам придется перекомпилировать C.m
, даже если C.m
не использует ни одного из вещи, определенные в A.h
. Это может привести к действительно ужасному и ненужному оттоку сборки, особенно если у вас часто меняются заголовки (как обычно на ранних стадиях разработки).
Первая цель похвальна, но для небольших проектов, кого это волнует? У вас есть четырехъядерный Pro, и полная сборка занимает пару минут, верно? Но вам все равно придется беспокоиться о второй проблеме: циклических зависимостях. A.h
класс ссылок B
и B.h
класс ссылок A
. На самом деле это может происходить довольно часто и может невинно закрасться в систему. Объект коллекции может ссылаться на тип объектов, которые он содержит, а объекты могут ссылаться на тип объекта коллекции. Все, что требуется, это одна ссылка из-за какого-то метода, который принимает или возвращает этот тип. Если у вас есть заголовки, импортирующие другие заголовки, вероятность того, что это произойдет, быстро приближается к единице. Вы получите рекурсивный импорт, и ошибки во время компиляции могут быть ошеломляющими. «Я знаю , что typdef определен! Он тут же! Он импортирован!» Но он еще не был проанализирован, когда вы импортировали этот заголовок. Это то, что вызывает вашу ошибку выше.
По этой причине, даже если вы не слишком заботитесь о времени сборки (хотя и должны), избегайте импорта заголовков в заголовки ... кроме ....
Некоторые заголовки, которые вы должны импортировать. Ваш суперкласс, конечно. Файлы, которые определяют @protocol
, который вы реализуете или typedef
, который вы используете. Так что да, вы должны включить их.
А как насчет системных заголовков? Ну, они никогда не будут вызывать отток, и, очевидно, они не будут вызывать рекурсивный импорт, поэтому они в порядке. Я не рекомендую людям использовать @class
предварительные объявления для вещей в системных заголовках. Это создает дополнительную работу для пользователя вашего заголовка без значения. Для обеспечения надлежащей гигиены заголовков, пожалуйста, не забудьте заключить системные заголовки в <угловые скобки>, а ваши заголовки - в «кавычки».
Так что это не тривиальный вопрос, а простое правило: избегайте импорта пользовательских заголовков в другие пользовательские заголовки всякий раз, когда компилятор позволит вам.