Вызов метода для категории, включенной из статической библиотеки iPhone, вызывает NSInvalidArgumentException - PullRequest
33 голосов
/ 01 июня 2009

Я создал статическую библиотеку для размещения некоторых из моих кодов, подобных категориям.

У меня есть категория для UIViews в "UIView-Extensions.h" с именем Extensions.

В этой категории у меня есть метод с именем:

- (void)fadeOutWithDelay:(CGFloat)delay duration:(CGFloat)duration;

Вызов этого метода отлично работает на симуляторе в конфигурации отладки.

Однако, если попытаться запустить приложение на устройстве, я получаю NSInvalidArgumentException:

[UIView fadeOutWithDelay:duration:]: unrecognized selector sent to instance 0x1912b0
 *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[UIView fadeOutWithDelay:duration:]: unrecognized selector sent to instance 0x1912b0

По какой-то причине UIView-Extensions.h, по-видимому, не включается в сборки устройства.


Что я проверял / пробовал

Я попытался включить другую категорию для NSString, и у меня возникла та же проблема.

Другие файлы, такие как целые классы и функции, работают нормально. Это проблема, что только происходит с категориями.

Я очистил все цели, которые не устранили проблему.

Я проверил проект статической библиотеки, категории включены в целевые группы "заголовки копирования" и "источники компиляции".

Статическая библиотека включена в группу проектов "связать бинарный файл с библиотекой".

Еще один проект, в который я добавил статическую библиотеку, работает просто отлично.

Я удалил и повторно добавил статическую библиотеку, не повезло

- установлен флаг компоновщика ObjC

Есть идеи?


нм выход

libFJSCodeDebug.a(UIView-Extensions.o):
000004d4 t -[UIView(Extensions) changeColor:withDelay:duration:]
00000000 t -[UIView(Extensions) fadeInWithDelay:duration:]
000000dc t -[UIView(Extensions) fadeOutWithDelay:duration:]
00000abc t -[UIView(Extensions) firstResponder]
000006b0 t -[UIView(Extensions) hasSubviewOfClass:]
00000870 t -[UIView(Extensions) hasSubviewOfClass:thatContainsPoint:]
000005cc t -[UIView(Extensions) rotate:]
000002d8 t -[UIView(Extensions) shrinkToSize:withDelay:duration:]
000001b8 t -[UIView(Extensions) translateToFrame:delay:duration:]
         U _CGAffineTransformRotate
000004a8 t _CGPointMake
         U _CGRectContainsPoint
         U _NSLog
         U _OBJC_CLASS_$_UIColor
         U _OBJC_CLASS_$_UIView
         U ___CFConstantStringClassReference
         U ___addsf3vfp
         U ___divdf3vfp
         U ___divsf3vfp
         U ___extendsfdf2vfp
         U ___muldf3vfp
         U ___truncdfsf2vfp
         U _objc_enumerationMutation
         U _objc_msgSend
         U _objc_msgSend_stret
         U dyld_stub_binding_helper

Ответы [ 9 ]

30 голосов
/ 10 июня 2009

Единственное решение, которое сработало, было включать:

"- all_load"

в других флагах компоновщика.

РЕДАКТИРОВАНИЕ: Обязательно добавьте этот флаг в проект, включая статическую библиотеку, а не в саму статическую библиотеку.

Я знаю, что это неправильный метод, но сейчас он работает.

Возможно, это проблема ОС 3.0, так как это было обходным решением для Three20.

14 голосов
/ 01 июня 2009

К сожалению, из-за того, какие категории работают и динамического характера среды выполнения Objective C, не все хорошо работает со статическими библиотеками. Причина, по которой вы получаете эту ошибку, заключается в том, что реализация категории в статической библиотеке фактически никогда не связана с исполняемым образом, потому что компилятор не может знать, что код реализации потребуется во время выполнения.

Чтобы вылечить это, вы можете заставить компоновщик копировать объектные файлы из статического архива для любого и всех изображений класса и категории Objective-C. Недостатком является то, что ваш исполняемый файл будет включать в себя код изображения для классов, которые вы можете вообще не использовать. Чтобы компоновщик включил код категории, добавьте -ObjC к настройке сборки OTHER_LD_FLAGS в Xcode. Ваша реализация категории теперь будет скопирована из статического архива в ваш исполняемый файл, и вы не получите исключение времени выполнения.

6 голосов
/ 11 июня 2010

Я только что говорил с инженером Apple об этом, и это было решено в ld с версиями> 100. Это включено в XCode4. Он провел меня через это, и я попробовал это сам, и действительно, проблема категории устранена.

Удалите «-all_load» и вернитесь к «-ObjC» в настройках сборки с новым компоновщиком.

5 голосов
/ 07 августа 2010

Если вы работаете в Xcode 3.2, вы можете избежать использования -all_load и вместо этого использовать -force_load только для рассматриваемой библиотеки, что должно быть немного более эффективным.

Это описано в недавно обновленном техническом тесте Apple: http://developer.apple.com/mac/library/qa/qa2006/qa1490.html

3 голосов
/ 10 февраля 2012

Проблема с необходимостью флагов компоновщика -all_load или -force_load для категорий ссылок была исправлена ​​в LLVM . Исправление поставляется в составе LLVM 2.9. Первая версия Xcode, в которой содержится исправление, - это поставка Xcode 4.2 с LLVM 3.0. Упомянутые исправления больше не нужны при работе с Xcode 4.2. Флаг -ObjC все еще необходим при связывании двоичных файлов ObjC

2 голосов
/ 30 мая 2012

У меня была такая же проблема, но добавление любой комбинации описанных флагов (-ObjC, -all_load, -force_load) не сработало.

Оказалось, что я не установил флажок "Добавить в цель" при добавлении файлов в проект. Я удалил файлы из проекта и добавил их снова, на этот раз убедившись, что этот флажок установлен. Это решило проблему.

2 голосов
/ 24 марта 2010

Я столкнулся с этой проблемой недавно. Я не смог заставить работать -all_load, когда заметил, что другая категория у меня работала. Я был ленив для этой категории и включил ее в другой файл.

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

Это было на iPhone OS 3.1.3.

Конечно, это НЕ ПРАВИЛЬНЫЙ способ исправить это, но, похоже, это сработало.

Полный пример кода есть в моем блоге для моих (тривиальных) категорий.

0 голосов
/ 21 апреля 2010

У меня была такая же проблема с категориями в моей статической библиотеке. В моем случае «-all_load» не помог, так как это вызвало множество ошибок сборки (моя статическая библиотека является оберткой вокруг другой частной библиотеки C / C ++).

Я решил это с помощью хака, предложенного на http://iphonedevelopmentexperiences.blogspot.com/2010/03/categories-in-static-library.html, который просто включал добавление фиктивного (пустого) определения класса в файлы категорий. Используя этот хак, я сохранил «-ObjC», но сбросил «-all_load» в настройках компоновщика приложения, и он отлично работал на устройстве.

0 голосов
/ 14 июня 2009

Раньше мне удавалось принудительно связать категорию с помощью -u .objc_category_name_UIView_Extensions, но в среде разработчика 3.0 это не работает, и единственным вариантом, кажется, -all_load.

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