Класс X реализован как в Y, так и в Z. Будет использован один из двух - PullRequest
12 голосов
/ 17 января 2012

У меня есть программа-инструмент "target" c (консоль), которая динамически загружает связки target-c во время выполнения. Некоторые файлы пакета совместно используют классы из одной и той же среды, поэтому я получаю сообщение «Класс реализован в обоих ...», выгруженное в консоль.

Это ничего не мешает работать, но наличие сообщений на консоли несколько раздражает. Есть ли способ, чтобы не допустить их там? Есть ли способ изменить пакет, чтобы они не компилировали / не связывали одни и те же классы?

Ответы [ 4 ]

3 голосов
/ 27 апреля 2012

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

  1. Создайте сценарий предварительной сборки, который анализирует все объявления @interface в заголовочных файлах и собирает все имена классов. Этот скрипт генерирует новый заголовок, который содержит что-то вроде следующего:

    #define MyClass        MyClass_Target
    #define MyOtherClass   MyOtherClass_Target
    #define MyThirdClass   MyThirdClass_Target
    

    (очевидно, суффикс _Target устанавливается параметром сборки, который ваш сценарий предварительной сборки может просматривать и использовать).

    Сценарий может быть скриптом Perl или Python, который просто сканирует каждый *.h файл, извлекая слово после @interface.

  2. Сконфигурируйте сборку для автоматического включения сгенерированного файла заголовка, чтобы вам не приходилось вручную включать сгенерированный заголовок в каждый исходный файл.

  3. Если ваши связки имеют перья, это добавляет дополнительный уровень сложности, но это все еще можно сделать. Создайте другой сценарий, который заменит существующий & ldquo; Nib Compiler & rdquo ;. Эта программа в основном выполняет то же переименование классов, но для перьев (это достаточно просто, потому что файлы перьев являются XML). Я не могу вспомнить, где его установить, но в XCode есть место, которое позволяет вам выбирать, как файлы Nib & ldquo; скомпилированы & rdquo ;. Ваш скрипт компилятора пера - это в основном оболочка, которая переименовывает классы в пирах, а затем вызывает реальный компилятор пера (который вы можете узнать, как он вызывается, посмотрев журнал сборки).

Это работает?

Да, и это работает на удивление хорошо, даже в ситуациях отладки. Когда вы достигаете точки останова, Xcode отображает имя класса с целевым суффиксом , чтобы вы знали, в каком пакете вы находитесь, несмотря на то, что исходный код показывает что-то другое. & ldquo; Исправить и продолжить & rdquo; все еще работал, насколько я помню.

Кроме того, поскольку переименование класса выполняется незадолго до времени компиляции, оно не влияет на такие вещи, как управление версиями исходного кода, взаимодействие с Interface Builder и т. Д.

Вопросы

  • Динамически сгенерированные имена классов не будут работать, например, Class объекты, возвращаемые из NSClassFromString, если в коде не указан необходимый суффикс.

  • Такая сложная установка требует небольшого обслуживания. После того, как я его запустил, он работал хорошо для наших нужд, но время от времени ему нужно было настроить его, чтобы он работал гладко.

3 голосов
/ 27 апреля 2012
  • Если это разные реализации, используйте уникальный префикс.

  • Если они имеют одинаковую реализацию и просто экспортированы более чем одним изображением, перенастройте ваши цели так, чтобы они экспортировались только одним.

В частности:

Есть ли способ изменить пакет, чтобы они не компилировали / связывали одни и те же классы?

Поместите эти общие классы в отдельную структуру и не компилируйте их как часть пакета - просто свяжите пакет с каркасом общей вещи.

0 голосов
/ 27 октября 2014

Если вы разработчик комплекта плагинов, вы можете передать -undefined dynamic_lookup как другие флаги компоновщика и удалить все библиотеки из плагина, которые дублируются в обоих (в основном бинарном и в плагине)

0 голосов
/ 17 января 2012

Вы пробовали только добавлять заголовки (@interface s) общих классов к пакетам (чтобы компилятор знал об API), но не кодовые файлы (@implementation s)?

Поскольку вы связываете пакет, компоновщик (ld) не должен жаловаться, что он не может найти реализации данных классов - он делегирует эту задачу динамическому компоновщику (dyld), который пинает за один раз вы загружаете пакет в свою основную программу. dyld должен автоматически установить необходимые ссылки между комплектом и программой.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...