Что лучший способ состоит в том, чтобы решить конфликт пространства имен Objective C?

Указатель NULL - это тот, который указывает на никуда. Когда вы разыскиваете указатель p, вы говорите «дайте мне данные в месте, хранящемся в« p ». Когда p является нулевым указателем, местоположение, хранящееся в p, является nowhere, вы говорите «Дайте мне данные в месте« нигде ». Очевидно, он не может этого сделать, поэтому он выбрасывает NULL pointer exception.

В общем, это потому, что что-то не было правильно инициализировано.

174
задан Jonas 26 January 2011 в 13:06
поделиться

9 ответов

Если Вы не должны использовать классы от обеих платформ одновременно, и Вы нацелены на платформы, которые поддерживают NSBundle разгрузка (OS X 10.4 или позже, никакая поддержка GNUStep), и производительность действительно не является проблемой для Вас, я полагаю, что Вы могли загрузить одну платформу каждый раз, когда необходимо использовать класс от него, и затем разгрузить его и загрузить другой, когда необходимо использовать другую платформу.

Моя начальная идея состояла в том, чтобы использовать NSBundle для загрузки одной из платформ, затем скопировать или переименовать классы в той платформе, и затем загрузить другую платформу. Существует две проблемы с этим. Во-первых, я не мог найти, что функция скопировала данные, на которые указывают, чтобы переименовать или скопировать класс, и любые другие классы в той первой платформе, которые ссылаются на переименованный класс, теперь сослались бы на класс от другой платформы.

Вы не должны были бы скопировать или переименовать класс, если бы был способ скопировать данные, на которые указывает IMP. Вы могли создать новый класс и затем скопировать по ivars, методам, свойствам и категориям. Намного больше работы, но это возможно. Однако у Вас все еще была бы проблема с другими классами в платформе, ссылающейся на неправильный класс.

РЕДАКТИРОВАНИЕ: принципиальное различие между C и временем выполнения Objective C, насколько я понимаю, когда библиотеки загружаются, функции в тех библиотеках содержат указатели на любые символы, на которые они ссылаются, тогда как в Objective C, они содержат строковые представления названий thsoe символов. Таким образом, в Вашем примере, можно использовать dlsym, чтобы получить адрес символа в памяти и присоединить его к другому символу. Другой код в библиотеке все еще работает, потому что Вы не изменяете адрес исходного символа. Objective C использует таблицу поиска для имен класса сопоставления к адресам, и это - отображение 1-1, таким образом, у Вас не может быть двух классов с тем же именем. Таким образом, для загрузки обоих классов одному из них нужно было изменить их имя. Однако, когда другие классы должны получить доступ к одному из классов с тем именем, они попросят у таблицы поиска ее адреса, и таблица поиска никогда не будет возвращать адрес переименованного класса, учитывая имя исходного класса.

47
ответ дан 2 revs 23 November 2019 в 20:32
поделиться

Добавление префикса файлов является простым решением, о котором я знаю. У Cocoadev есть страница пространства имен, которая является усилием сообщества избежать конфликтов пространства имен. Не стесняйтесь добавлять свое собственное к этому списку, я верю тому, для именно это это.

http://www.cocoadev.com/index.pl?ChooseYourOwnPrefix

0
ответ дан Ryan Townshend 23 November 2019 в 20:32
поделиться

Если бы у Вас есть коллизия, я предложил бы, чтобы Вы думали трудно о том, как Вы могли бы осуществить рефакторинг одну из платформ из Вашего приложения. Наличие коллизии предполагает, что эти два делают подобные вещи, как это, и Вы, вероятно, могли обойти использование дополнительной платформы просто путем рефакторинга приложения. Мало того, что это решило бы Вашу проблему пространства имен, но и она сделает Ваш код более устойчивым, легче поддержать, и более эффективный.

По большему техническому решению, если бы я был в Вашем положении, это было бы моим выбором.

0
ответ дан Allyn 23 November 2019 в 20:32
поделиться

Отчаянные положения призывают к отчаянным мерам. Вы рассмотрели взламывание объектного кода (или файл библиотеки) одной из библиотек, изменив сталкивающийся символ на альтернативное имя - той же длины, но другого написания (но, рекомендация, та же длина имени)? По сути противный.

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

3
ответ дан Jonathan Leffler 23 November 2019 в 20:32
поделиться

Вы рассмотрели использование функций времени выполнения (/usr/include/objc/runtime.h) для клонирования одного из конфликтующих классов к не сталкивающемуся классу и затем загрузки сталкивающейся платформы класса? (это потребовало бы, чтобы сталкивающиеся платформы были загружены в разное время для работы.)

можно осмотреть классы ivars, методы (с именами и адресами реализации) и именами со временем выполнения, и создать собственное также динамично, чтобы иметь то же ivar расположение, адреса имен/реализации методов, и только отличаться по имени (для предотвращения коллизии)

4
ответ дан xtophyr 23 November 2019 в 20:32
поделиться

Это грубо, но Вы могли использовать распределенные объекты для хранения одного из классов только в зависимом адресе программ и RPC к нему. Это станет грязным, если Вы передадите тонну материала назад и вперед (и может не быть возможным, если оба класса непосредственно управляют представлениями, и т.д.).

существуют другие потенциальные решения, но многие из них зависят от точной ситуации. В частности, Вы использующий современное или время выполнения прежней версии, Вы толстая или единая архитектура, 32 или 64 бита, какие версии ОС - Вы предназначение, являются Вами динамично соединение, статически соединение, или делают у Вас есть выбор, и это потенциально хорошо, чтобы сделать что-то, что могло бы потребовать обслуживания для новых обновлений программного обеспечения.

, Если Вы являетесь действительно отчаянными, что Вы могли сделать:

  1. Не связываются против одной из библиотек непосредственно
  2. Реализация альтернативная версия objc стандартных программ во время выполнения, которая меняет имя во время загрузки (контроль проект objc4, что точно необходимо сделать, зависит в ряде вопросов, которые я задал выше, но должно быть возможно независимо от того, что ответы).
  3. Использование что-то как mach_override для введения новой реализации
  4. Загрузка новая библиотека с помощью нормальных методов это пройдет исправленную стандартную программу компоновщика и доберется, ее имя класса изменилось

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

8
ответ дан Louis Gerbarg 23 November 2019 в 20:32
поделиться

Добавление префикса Ваших классов с уникальным префиксом является существенно единственной опцией, но существует несколько способов сделать это менее обременительным и ужасным. Существует долгое обсуждение опций здесь . Мой фаворит @compatibility_alias директива компилятора Objective C (описал здесь ). Можно использовать @compatibility_alias для "переименовывания" класса, позволяя Вам назвать Ваш класс с помощью FQDN или некоторого такого префикса:

@interface COM_WHATEVER_ClassName : NSObject
@end

@compatibility_alias ClassName COM_WHATEVER_ClassName
// now ClassName is an alias for COM_WHATEVER_ClassName

@implementation ClassName //OK
//blah
@end

ClassName *myClass; //OK

Как часть полной стратегии, Вы могли снабдить префиксом все свои классы уникальный префикс, такие как FQDN и затем создать заголовок с весь @compatibility_alias (я предположу, что Вы могли автоматически сгенерировать было, сказано в заголовке).

оборотная сторона добавления префикса как это - то, что необходимо ввести истинное имя класса (например, COM_WHATEVER_ClassName выше) в чем-либо, чему нужно имя класса от строки помимо компилятора. В частности, @compatibility_alias директива компилятора, не, функция времени выполнения так NSClassFromString(ClassName) перестанет работать (возврат nil) - необходимо будет использовать NSClassFromString(COM_WHATERVER_ClassName). Можно использовать ibtool через фазу разработки для изменения имен классов в Интерфейсном Разработчике nib/xib так, чтобы Вы не писали полный COM_WHATEVER_... в Интерфейсном Разработчике.

Заключительный протест: потому что это - директива компилятора (и неясный в том), это не может быть портативно через компиляторы. В частности, я не знаю, работает ли это с Лязгом frontend из проекта LLVM, хотя это должно работать с LLVM-GCC (LLVM использование GCC frontend).

93
ответ дан Eonil 23 November 2019 в 20:32
поделиться

Кажется, что проблема - то, что Вы не можете сослаться на файлы заголовков от обеих систем в той же единице перевода (исходный файл). Если Вы создаете объективные-c обертки вокруг библиотек (делающий их более применимый в процессе), и только #include заголовки для каждой библиотеки в реализации классов обертки, которые эффективно разделили бы коллизии имени.

у меня нет достаточного опыта с этим в цели-c (просто начинающий), но я верю тому, именно это я сделал бы в C.

1
ответ дан chrish 23 November 2019 в 20:32
поделиться

Несколько человек уже поделились хитрым и умным кодом, который может помочь решить проблему. Некоторые из предложений могут работать, но все они далеко не идеальны, а некоторые из них совершенно неприятны для реализации. (Иногда уродливые взломы неизбежны, но я стараюсь избегать их, когда могу.) С практической точки зрения вот мои предложения.

  1. В любом случае, проинформируйте разработчиков обоих фреймворков о конфликте. , и дать понять, что их неспособность избежать и / или решить эту проблему вызывает у вас реальные бизнес-проблемы, которые, если не будут решены, могут привести к потере дохода. Подчеркните, что хотя разрешение существующих конфликтов для каждого класса является менее навязчивым решением, полностью меняя их префикс (или используя его, если их сейчас нет, и позор им! ) - лучший способ убедиться, что они больше не столкнутся с той же проблемой.
  2. Если конфликты имен ограничиваются достаточно небольшим набором классов, посмотрите, сможете ли вы обойти только эти классы, особенно если один из конфликтующие классы прямо или косвенно не используются вашим кодом. Если да, посмотрите, предоставит ли поставщик настраиваемую версию платформы, не включающую конфликтующие классы. Если нет, скажите откровенно о том, что их негибкость снижает вашу рентабельность инвестиций от использования их фреймворка. Не расстраивайтесь из-за того, что проявляете настойчивость в разумных пределах - клиент всегда прав. ; -)
  3. Если один фреймворк более "необязательный", вы можете подумать о его замене другим фреймворком (или комбинацией кода), сторонним или самодельным. (Последнее является нежелательным худшим случаем, поскольку это, безусловно, повлечет за собой дополнительные бизнес-расходы, как на разработку, так и на сопровождение.) Если вы это сделаете, сообщите поставщику этой инфраструктуры, почему вы решили не использовать их среду.
  4. Если обе платформы считаются одинаково необходимыми для вашего приложения, изучить способы разделения использования одного из них на один или несколько отдельных процессов, возможно, общение через DO, как предложил Луи Гербарг. В зависимости от степени общения это может быть не так плохо, как вы могли ожидать. Некоторые программы (включая QuickTime, я полагаю) используют этот подход для обеспечения более детальной безопасности, обеспечиваемой использованием профилей песочницы Seatbelt в Leopard , так что только определенному подмножеству вашего кода разрешено выполнять критические или чувствительные операции. Производительность будет компромиссом, но может быть вашим единственным вариантом

I ' я предполагаю, что лицензионные сборы, сроки и сроки могут помешать немедленным действиям по любому из этих пунктов. Надеюсь, вы сможете разрешить конфликт как можно скорее. Удачи!

12
ответ дан 23 November 2019 в 20:32
поделиться