Мій запит такий. Коли використовується #import і коли використовується @class?
Проста відповідь: Ви #import
або #include
коли є фізична залежність. В іншому випадку, можна використовувати вперед декларацій ( @class MONClass
, struct MONStruct
, @protocol MONProtocol
).
Ось кілька поширених прикладів фізичної залежності:
- Будь-яке значення C або C ++ (вказівник або посилання не є фізичною залежністю). Якщо у вас є
CGPoint
ivar або властивість, компілятору необхідно переглянути декларацію CGPoint
.
- Ваш суперклас.
- Метод, який ви використовуєте.
Іноді, якщо я використовую декларацію @class, я бачу загальне попередження компілятора, таке як: "попередження: приймач 'FooController' - це клас прямого переходу, і відповідний @ інтерфейс може не існувати."
Насправді компілятор дуже м'який. Він видасть підказки (наприклад, описаний вище), але ви можете легко виправити свій стек, якщо проігнорувати їх і не виконати #import
належним чином. Хоча це повинно (IMO), компілятор цього не виконує. У ARC компілятор є більш суворим, оскільки він відповідає за підрахунок посилань. Що відбувається - компілятор відпадає від за замовчуванням, коли він стикається з невідомим методом, який ви викликаєте. Кожне повернене значення та параметр вважається рівним id
. Таким чином, вам слід викорінювати кожне попередження зі своїх кодових баз, оскільки це слід вважати фізичною залежністю. Це аналогічно виклику функції C, яка не оголошується. З С параметри приймаються такими, що є int
.
Причина, за яку ви віддаєте перевагу переадресаційним деклараціям, полягає в тому, що ви можете скоротити час складання на фактори, оскільки існує мінімальна залежність. За допомогою прямого декларування компілятор бачить, що є ім'я, і може правильно розбирати та компілювати програму, не бачачи декларації класу або всіх її залежностей, коли фізичної залежності немає. Чисті конструкції займають менше часу. Поступові нарощування займають менше часу. Звичайно, ви витратите трохи більше часу, переконавшись, що всі необхідні заголовки будуть видимими для кожного перекладу як наслідок, але це окупається в скорочені терміни складання (припустимо, що ваш проект не крихітний).
Якщо ви використовуєте #import
або #include
замість цього, ви кидаєте набагато більше роботи на компілятор, ніж потрібно. Ви також вводите складні залежності заголовків. Це можна порівняти з алгоритмом грубої сили. Коли ви #import
, ви перетягуєте тонни непотрібної інформації, що вимагає багато пам’яті, дискового вводу / виводу та процесора для розбору та компіляції джерел.
ObjC досить близький до ідеального для мови, що базується на C, залежно від залежності, оскільки NSObject
типи ніколи не є значеннями - NSObject
типи завжди посилаються на лічильник покажчиків. Таким чином, ви можете піти з неймовірно швидким часом компіляції, якщо структурувати залежність своєї програми належним чином і вперед, де це можливо, тому що фізична залежність потрібна дуже мало. Ви також можете оголосити властивості в розширеннях класів, щоб додатково мінімізувати залежність. Це величезний бонус для великих систем - ви б знали різницю, якщо ви коли-небудь розробляли велику C ++ базу даних.
Тому моя рекомендація - використовувати вперед, де це можливо, а потім туди, #import
де є фізична залежність. Якщо ви бачите попередження чи інше, що передбачає фізичну залежність - виправте їх усі. Виправлення полягає #import
у вашому файлі реалізації.
Коли ви будуєте бібліотеки, ви, швидше за все, класифікуєте деякі інтерфейси як групу; у цьому випадку ви використовуєте #import
ту бібліотеку, де введена фізична залежність (наприклад #import <AppKit/AppKit.h>
). Це може ввести залежність, але бібліотечні працівники часто можуть обробляти фізичні залежності для вас за потреби - якщо вони вводять функцію, вони можуть мінімізувати вплив, який вона має на ваші побудови.