Objective-c — заменить #import на #define

Есть ли способ заменить имя класса #import с помощью макроса #define? Я хочу, чтобы это было сделано во всем моем проекте, а не только в одном файле. Поэтому я не хочу создавать #ifdef / #ifndef в каждом классе, который включает #import, который я хочу заменить.

Что-то вроде... у меня есть

#import "ClassSomething.h" 

в 5 классах. Я хочу заменить его на

#import "ClassSomethingCustom.h" 

но только

#ifdef SomethingIsDefined

person Alberto Schiariti    schedule 27.11.2014    source источник
comment
Это действительно плохой дизайн.   -  person Ben Affleck    schedule 03.12.2014
comment
@Энди: я знаю это. Может быть, иногда вас заставляют это делать или вы думаете, что я люблю плохой дизайн? :-)   -  person Alberto Schiariti    schedule 03.12.2014
comment
Я понимаю. Может быть, вы могли бы обойтись без категорий или, может быть, вы могли бы переключить ISA на современную среду выполнения. Иногда лучший подход — скопировать код и изменить его, если вы планируете кардинальные изменения. Становится менее рискованно. Или, может быть, вы могли бы решить это на уровне файловой системы и создать символические ссылки или что-то в этом роде. Есть много способов.   -  person Ben Affleck    schedule 03.12.2014
comment
Я думаю, вам нужно перепроверить архитектуру импорта, очень плохая идея...   -  person Vitalii Gozhenko    schedule 06.12.2014


Ответы (4)


Во-первых, компилятор Objective-C (gcc или clang) хорошо справляется с тем, что не загромождает скомпилированный исходный код дублирующейся информацией заголовка. Нет ничего плохого в том, чтобы включить оба заголовка, если только заголовки не переопределяют один и тот же класс (что, как я подозреваю, имеет место здесь).

Замените #import "ClassSomething.h" во всех ваших файлах на #import CLASS_SOMETHING_HEADER

Затем в вашем файле .pch есть следующее:

#ifdef SomethingIsDefined
    #define CLASS_SOMETHING_HEADER "ClassSomethingCustom.h" 
#else
    #define CLASS_SOMETHING_HEADER "ClassSomething.h"
#endif

Однако на самом деле это не идеально, так как макросы препроцессора, имеющие дело с импортом, могут привести ко многим непредвиденным ошибкам. Это не распространенный шаблон, и будущие разработчики могут не понять, что вы сделали.

Другой вариант, который вы, возможно, захотите рассмотреть, — это шаблон, который обычно используется в библиотеках, поддерживающих как iOS, так и OS X.

#ifdef SOME_IOS_IDENTIFIER_I_FORGOT_TO_LOOK_UP
    typedef UIColor MyColor
#else
    typedef NSColor MyColor
#endif

В этом случае вы должны назвать два класса по-разному и использовать псевдоним для ссылки на них в исходном коде. Поместите соответствующий импорт в «родительский» заголовочный файл, например «MyProjectImports.h» или что-то в этом роде. (где вы бы импортировали AppKit или UIKit)

В качестве альтернативы вы можете рассмотреть возможность использования Category на ClassSomething (т. е. «ClassSomething+Custom.h»), чтобы включить необходимые вам пользовательские функции. Это, вероятно, потребует некоторой переработки логики, лежащей в основе двух разных классов, но в файлах, которым требуется только пользовательское поведение, можно условно #import заголовок категории, а другие файлы можно оставить в покое.

Без дополнительных сведений о том, чем эти два класса отличаются или будут использоваться, я не смогу вам помочь.

HtH

person Stephen Furlani    schedule 08.12.2014

Поместите это в заголовочный файл:

#ifdef SomethingIsDefined
#import "ClassSomethingCustom.h" 
#else
#import "ClassSomething.h"
#endif

и включите этот заголовочный файл в свои 5 классов.

person dasdom    schedule 27.11.2014
comment
Я думал об этом, но таким образом мне нужно создать заголовок для каждого класса, который я хочу настроить. Будет работать, но я искал что-то более программное. Вроде единый заголовок, где все эти подмены сделаны. И я также не хотел изменять все проекты, в которых уже есть #import ClassSomething.h. - person Alberto Schiariti; 27.11.2014

Вы можете изменить содержимое ClassSomething.h и поместить только #ifdef SomethingIsDefined туда.

person alediaferia    schedule 01.12.2014
comment
Это не поможет. Мне нужно импортировать ClassSomethingCustom вместо ClassSomething, поэтому я должен внести это изменение в класс, который теперь включает ClassSomething. Не в самом этом классе. - person Alberto Schiariti; 01.12.2014
comment
Если вы не хотите редактировать 5 источников, включающих ClassSomething.h, единственный способ — отредактировать сам ClassSomething.h так, чтобы, если SomethingIsDefined определен, он открывал ClassSomething, в противном случае он открывал ClassSomethingCustom. Это означает, что вам придется поместить объявления ClassSomething и ClassSomethingCustom внутрь ClassSomething.h и переключать их через файл #ifdef. - person alediaferia; 01.12.2014

Возможно, вам нужно вставить код, написанный @dasdom, в ваш файл .pch (предварительно скомпилированный заголовок) вместо каждого заголовка. При этом вам нужно вставить его только один раз, и все файлы будут автоматически добавлять этот заголовок.

#ifdef SomethingIsDefined
#import "ClassSomethingCustom.h" 
#else
#import "ClassSomething.h"
#endif

Я надеюсь, это поможет вам. В противном случае, пожалуйста, не могли бы вы объяснить это глубоко?

person jomafer    schedule 01.12.2014
comment
Как я сказал @dasdom, это не соответствует моему вопросу, потому что таким образом все мои классы будут включать либо ClassSomethingCustom, либо ClassSomething. Это было бы выгодно, если бы у меня было не так много классов для настройки. Я не могу импортировать во все классы, например 25-30 классов, которые я не буду использовать. P.S. Большая проблема заключается в том, что я делаю основной проект, который будет включен в другие проекты, но он должен адаптироваться к этим проектам, если они реализуют настройку классов или их основную версию. - person Alberto Schiariti; 01.12.2014
comment
@AlbertoSchiariti Я буду честен с вами, я не думаю, что есть какой-либо другой способ сделать то, что вам нужно, кроме способов, которые вам предлагают, и вы говорите, что они не подойдут. - person Popeye; 01.12.2014
comment
@ Попай, у меня был подозреваемый. Вот почему я хотел услышать некоторых коллег здесь :-) - person Alberto Schiariti; 01.12.2014