Технические вопросы и ответы QA1490

Создание Objective C статические библиотеки с категориями

Q: Как я фиксирую «селектор не распознанные» исключения на этапе выполнения при попытке использовать методы категории от статической библиотеки?

A: Если Вы видите «селектор не распознанное» исключение на этапе выполнения при вызове метода категории, реализованного в статической библиотеке, Вы поражаете разовую ссылкой проблему сборки, описанную здесь, и должны добавить флаг компоновщика-ObjC к Вашему проекту путем выполнения этих шагов:

  1. В XCode выберите View> Navigators> Show Project Navigator или нажатие ⌘1.

  2. Выберите свой проект под PROJECT, возглавляющим в Навигаторе Проекта, затем выберите вкладку Build Settings.

  3. Прокрутите вниз к Другой установке сборки Флагов Компоновщика при Соединении набора или типа «Другие Флаги Компоновщика» в панель поиска.

  4. Установите значение Другой установки сборки Флагов Компоновщика в $(OTHER_LDFLAGS) -ObjC.

Рисунок 1  , Изменяющий Другую установку сборки Флагов Компоновщика

Поиск и устранение неисправностей

При добавлении -ObjC флаг не решает проблему, двойная проверка, чтобы конфликтная установка сборки Target не переопределила его, следующим вышеупомянутые шаги, но выбрала текущую цель под «TARGETS» на шаге 2 вместо проекта.

Другие Причины селектора не распознанные Исключения

Наиболее распространенные причины «селектора не распознанное» исключение:

Никакой такой метод

Метод действительно не существует. Проверьте свое написание. Проверьте документацию, чтобы проверить, что метод существует на версии операционной системы, которую использует Ваше приложение.

Управление памятью

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

Что вызывает те исключения?

Несоответствие импеданса между UNIX, статические библиотеки и динамический характер Objective C могут заставить методы категории в статических библиотеках не быть соединенными в приложение, приводящее к «селектору не распознанные» исключения, когда методы не найдены во время выполнения.

Компоновщик

Когда программа C компилируется, каждый «исходный файл» превращен в «объектный файл», содержащий исполнимые функции и статические данные. Компоновщик склеивает эти объектные файлы в заключительную исполнимую программу. Та исполнимая программа в конечном счете связывается в приложение XCode.

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

Например, если main.c использует функцию foo(), где foo определяется в другом файле, B.c, тогда объектный файл main.o будет иметь неразрешенный символ для foo(), и B.o будет включать реализацию foo(). Во время ссылки, B.o будет принесен в заключительную исполнимую программу, так, чтобы код в main.o теперь ссылается на реализацию foo() определенный в B.o.

UNIX статическая библиотека является просто набором объектных файлов. Если выполнение так разрешило бы некоторый неопределенный символ, обычно компоновщик только вытягивает в объектном файле от статической библиотеки. Получение по запросу во всех объектных файлах сокращает размер заключительной исполнимой программы.

Objective C

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

Например, если main.m включает код [[FooClass alloc] initWithBar:nil]; тогда main.o будет содержать неопределенный символ для FooClass, но никакие символы компоновщика для -initWithBar: метод будет в main.o.

Так как категории являются набором методов, использование метода категории не генерирует неопределенный символ. Это означает, что компоновщик не знает для загрузки объектного файла, определяющего категорию, если уже определяется сам класс. Это вызывает тот же «селектор не распознанное» исключение на этапе выполнения, Вы видели бы любой нереализованный метод.

Флаг компоновщика-ObjC

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



История версии документа


ДатаПримечания
05.08.2014

Удаленное обсуждение обходных решений, которые являются ненужными в Xcode 4 и позже. Добавленные указатели на большее количество частых причин 'селектора не распознанные' ошибки.

30.04.2010

Описывает, как передать опцию «-ObjC» компоновщику. Обновленный для Mac OS X v10.6 и позже.

03.10.2006

Измененный «и» к для создания содержания корректным.

25.09.2006

Новый документ, описывающий, как должным образом создать Objective C статические библиотеки, содержащие категории на существующих классах.