Импорт заголовка в цель c
В Objective-c, когда мы используем объект одного класса в другом классе по соглашению, мы должны заранее объявить класс в файле.h, т.е. @class classname;
, И следует импортировать заголовочный файл в файл.m, т.е. #import "header.h"
, Но если мы импортируем файл заголовка в.h, тогда нам не нужно импортировать его снова в файл.m. Так в чем же причина этого соглашения? Какой эффективный способ?
5 ответов
Так в чем же причина этого соглашения?
Вы должны отдать предпочтение форвардным декларациям (@class MONClass;
) где это возможно, потому что компилятор должен знать, что имя типа является классом objc перед его использованием, и потому что #import
может перетаскивать кучу других заголовков (например, целых фреймворков / библиотек), серьезно увеличивая и усложняя ваши зависимости и увеличивая время сборки.
Какой эффективный способ?
Форвард декларации. Ваши сборки, перестройки и индексация будут намного быстрее, если вы сделаете это правильно.
Вы правы, что импорт заголовка в.h делает подобное проще (в краткосрочной перспективе). Причина не делать этого и импортировать его в файл реализации (.m) состоит в том, чтобы предотвратить загрязнение имен, когда все имена в импортированном заголовке доступны, когда кто-то импортирует ваш заголовок. Вместо этого, импортируя ваш заголовок, должны импортироваться только ваши функции / классы, а остальное в реализации
Кроме того, если вы импортируете заголовок в.h, это означает, что каждый код, импортировавший ваш заголовок, должен будет перекомпилироваться при изменении стороннего заголовка, даже если ничего явно не изменилось в вашем заголовке. Прямое объявление устраняет эту проблему и заставляет перекомпилировать только те файлы реализации (.m), которые фактически используют сторонний заголовок.
Несмотря на то, что импорт файлов в.m облегчает работу с несколькими строками кода, но считается, что импорт может влиять на время загрузки и время отклика, да, это влияет и не влияет. Так как согласно документации от Apple:-
Если вы беспокоитесь о том, что включение основного заголовочного файла может привести к расширению вашей программы, не беспокойтесь. Поскольку интерфейсы Mac OS X реализованы с использованием каркасов, код для этих интерфейсов находится в динамической общей библиотеке, а не в вашем исполняемом файле. Кроме того, только код, используемый вашей программой, загружается в память во время выполнения, поэтому ваш объем памяти в памяти также остается небольшим.
Что касается включения большого количества заголовочных файлов во время компиляции, еще раз, не беспокойтесь. Xcode предоставляет предварительно скомпилированный заголовок для ускорения времени компиляции. Скомпилируя все заголовки фреймворка одновременно, нет необходимости перекомпилировать заголовки, если вы не добавите новый фреймворк. В то же время, вы можете использовать любой интерфейс из включенных фреймворков практически без потери производительности.
Таким образом, время отклика и загрузки влияют только в первый раз, но в любом случае предпочтение следует отдавать ссылкам вперед, чтобы поддерживать стандарты кодирования и избежать незначительных накладных расходов:).
#import
директива препроцессора, которая работает с файлом до того, как его увидит компилятор Всякий раз, когда вы запутались, концептуально думайте об этом как о копировании и вставке: когда вы видите #import foo
, означает, что содержимое файла foo вставляется в этот момент. (Это немного умнее, так как он также защищает от дубликатов включений).
Так что вы #import Foo.h
в Bar.h
если есть объявления в Bar.h
эта ссылка Foo.h
, Если нет ничего в Bar.h
который использует Foo, но есть Bar.m
, то импорт идет в Bar.m
, Храните декларации только там, где они нужны.
Это JST, чтобы сказать компилятор, у нас есть класс с именем xx, если вы используете @class xx;
потому что теперь его свойства / метод не нужны.
и в следующем случае вам также понадобятся свойства и методы, так как вам понадобится доступ к ним. это проблема, если вы используете @class xx в вашем файле.h и не импортируете xx.h. тогда объявление объекта xx не будет генерировать ошибку, но доступ к его методу вызовет предупреждение, а доступ к proprty вызовет ошибку