Ошибка «Неизвестный класс <MyClass> в файле Interface Builder» во время выполнения


260

Хотя Interface Builder знает об этом MyClass, я получаю сообщение об ошибке при запуске приложения.

Это происходит, когда MyClassявляется частью библиотеки, и не происходит, если я скомпилирую класс непосредственно в цели приложения.


Как вы ссылаетесь на библиотеку?
Elise van Looij

Я использую зависимый подпроект и выполнил drag'n'drop из продуктов подпроекта Xcode в фазу сборки моей текущей цели "Link Binary With Library".
jhoule

Если класс принадлежит CocoaPods, это может помочь github.com/CocoaPods/CocoaPods/issues/491 .
Протоколь

Может быть связано? stackoverflow.com/a/24924967/511299
Sunkas

Ответы:


222

Несмотря на ошибку « Неизвестный класс MyClass в файле Interface Builder. », Напечатанную во время выполнения, эта проблема не имеет ничего общего с Interface Builder, а связана с компоновщиком, который не связывает класс, поскольку ни один код не использует его напрямую.

Когда данные .nib (скомпилированные из .xib) загружаются во время выполнения, на MyClassних ссылаются с помощью строки, но компоновщик не анализирует функциональность кода, а только существование кода, поэтому он этого не знает. Поскольку никакие другие исходные файлы не ссылаются на этот класс, компоновщик оптимизирует его при создании исполняемого файла. Поэтому, когда код Apple пытается загрузить такой класс, он не может найти связанный с ним код и выводит предупреждение.

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

Хак, который я изначально использовал, заключался в добавлении пустой статической подпрограммы, например:

+(void)_keepAtLinkTime;

который ничего не делает, но я бы назвал один раз, например:

int main( int argc, char** argv )
{
   [MyClass _keepAtLinkTime];
   // Your code.
}

Это заставит компоновщик сохранить весь класс, и ошибка исчезнет.

Как указал в комментариях jlstrecker, нам не нужно добавлять _keepAtLinkTimeметод. Просто вызывая существующий, такой как:

   [MyClass class];

делает трюк (до тех пор, пока вы производите от NSObject).

Конечно, вы можете назвать это в любом месте вашего кода. Я думаю, что это может быть даже в недоступном коде. Идея состоит в том, чтобы обмануть линкера в том, MyClassчто он где-то используется, чтобы он не был таким агрессивным в его оптимизации.

Xcode 6.3.2 и Swift 1.2

Быстрое определение зрения. Обязательно переопределите init(coder aDecoder: NSCoder). Objective-C определение представления контроллера. И перо в грушевом дереве.

Добавьте Имя модуля в инспектор деталей Nib, где вы выбираете свой класс.


2
Данные .xib не загружаются во время выполнения. Компилятор IB компилирует xib в nib; nib - это то, что загружается во время выполнения.
Питер Хоси

19
Вам не нужно изменять MyClass. Просто вызовите метод, от которого он наследует NSObject, например +class.
jlstrecker

10
Хотя это был не Xcode 4, когда оригинальный вопрос был опубликован, следующее все еще кажется уместным. В Xcode 4 вместо добавления некоторого фиктивного метода, чтобы устранить ошибку, вы можете проверить все необходимые цели MyClass.mв разделе Target Membership File Inspector.
adubr

51
Еще одна возможность в наши дни заключается в том, что MyClass.m может не находиться на этапе сборки исходных кодов. Это может произойти, если вы перетащите MyClass.h / m в свой проект, а не создадите их с помощью New File.
Стивен Фишер

6
@JoshBruce вы можете объяснить решение Swift? Я не очень понимаю это.
Райан Бобровски

183

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

  • Используя XCode 4, в Project Navigator выберите файл .m, который содержит класс, на который он жалуется

  • Перейдите в View-> Utilities-> Show File Inspector
    (это покажет File Inspector справа, с этой информацией .m-файла)

  • Откройте раздел Target Membership и убедитесь, что ваша цель выбрана для этого .m-файла

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


Это правда, что иногда ошибка компоновщика возникает из-за того, что вы просто не компилируете файл в своей цели. То, что вы описываете, - это способ управления целью (ами), с которой связан файл. К сожалению, мой файл уже был частью моей цели, но у меня все еще была проблема со ссылкой. Вероятно, это было связано с тем, что моя библиотека была C ++ (в отличие от Objective-C), которая имеет различные флаги компоновщика по умолчанию (см. Сообщения Alasdair Allan и Sijo выше).
2009 года

5
Это предложение сработало для меня, хотя и немного по-другому, поскольку мой флажок «Целевое членство» уже был установлен. Я снял флажок и пересобрал, но затем сообщение об ошибке изменилось, чтобы указать мое новое имя класса. Перепроверка коробки и сборка заново, теперь все работает. Гораздо проще, чем удалять файлы кеша!
электромагнитный

Отличное решение с помощью Xcode UI. @electromaggot, Xcode может запутаться, когда вы добавляете классы вручную, поэтому вам может потребоваться добавить более одного файла.
Гонен

Это решение для меня тоже. Я перетащил некоторые файлы классов из другого проекта, и эти файлы классов вызвали исключение.
Hairbo

1
Я удалил файл из своего проекта, затем добавил этот файл позже, и это решило проблему.
MindSpiker

70

Это на самом деле не имеет ничего общего с Interface Builder, здесь происходит то, что символы не загружаются из вашей статической библиотеки XCode. Для решения этой проблемы вам необходимо добавить -all_load -ObjCфлаги в Other Linker Flagsключ Project (и, возможно, Target) Build Settings.

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


5
Я обнаружил, что только -ObjCфлаг поменял его в моем случае.
Кекоа

5
@Kekoa, потому что ваша версия Xcode (LLVM) более поздняя, ​​чем тот, кто писал этот ответ. В настоящее время использование -ObjCдостаточно хорошо для решения проблемы.
до

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

-ObjC один флаг исправил мою проблему. Я действительно получил ошибку из-за атрибута all_load в iOS7.
Сушма Сатиш

Использование -all_load -ObjC может привести к ненужному увеличению размера продукта. эта проблема происходит с файлами категорий тоже только в рамках.
Али Амин

26

Я столкнулся с этой проблемой сегодня, используя Swift.

Я изменил класс Model.h + Model.mна Model.swift. Этот объект был использован в Интерфейсном Разработчике с class = Model.

Как только я заменил объект, класс больше не мог быть загружен.

Я должен был изменить ссылку на класс в IB с:

Class = Model
Module = 

в

Class = Model
Module = <TARGETNAME>

Вы найдете <TARGETNAME>в настройках сборки. Это также имя, которое отображается в созданном вами Swift-заголовке:#import "TARGETNAME-Swift.h"


1
Это кажется правильным ответом. Если кто-то не может сказать иначе, это должно быть помечено как правильное.
Бьорн Рутберг

1
Отличный ответ, спасибо. Для меня Moduleимя было прямо в раскрывающемся списке. Это было название моего приложения.
ChrisH

Меня устраивает. Для моей проблемы <TARGETNAME>, упомянутый в вашем ответе, является именем платформы, содержащей класс.
Тайлер Лонг

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

Для AppDelegate мне удалось исправить это в интерфейсе Interface Builder. Для пользовательского класса элемента пользовательского интерфейса в окне интерфейс Interface Builder не позволил бы мне установить пользовательский класс и модуль. Мне пришлось сделать следующее: (1) Откройте файл .xib как «Исходный код» (щелкните по нему правой кнопкой мыши). (2) Добавьте атрибут «customModule = <TARGETNAME>» рядом с атрибутом customClass.
Пулсбо

20

Перейдите к «ProjectName», нажмите на него, а затем перейдите на вкладку «Build фазы», ​​а затем нажмите «источники компиляции», а затем нажмите кнопку «+», появится окно, выберите «MyClass. m "файл, а затем нажмите" добавить ",

Постройте проект и запустите его, проблема наверняка будет решена


да, я не проверил ВСЕ целевые поля, которые я хотел добавить в свои недавно импортированные классы. Спасибо!
Джоэл Балмер

Да! Мой файл VC отсутствовал в целевом проекте.
Себастьян Дворник

19

Это проблема с кешем Xcode4, просто удалите все папки в / Users / your_user / Библиотека / Поддержка приложений / iPhone Simulator / 4.3 / Applications /

Кроме того, если у вас есть такая же проблема тестирования на вашем iPhone, удалите старое приложение перед его запуском ...

Удачи. Паскуаль


8
В настройках сборки проекта необходимо добавить флаги «-all_load -ObjC» к клавише «Другие флаги компоновщика». Это не специфическая проблема Xcode 4, и фактически вообще не имеет ничего общего с Interface Builder.
Alasdair Аллан

Это решение было предложено уже в январе 2010 года (см. Выше).
jhoule

6
Да, более простой способ сделать это - просто открыть симулятор iOS и в меню выбрать «Сбросить содержимое и настройки».
RanLearns,

Или вы можете сделать то, что я сделал, и просто удалить соответствующее приложение на главном экране симулятора. У меня было то же сообщение об ошибке, но оно ссылалось на старого делегата приложения.
spstanley

16

Иногда IBuilder пропускал customModule="AppName" customModuleProvider="target"

Чтобы исправить это, откройте раскадровку как исходный код и замените эту строку:

<viewController storyboardIdentifier="StoryboardId" id="SomeID" customClass="CustomClass"
sceneMemberID="viewController">

к этому:

<viewController storyboardIdentifier="StoryboardId" id="SomeID" customClass="CustomClass"
 customModule="AppName" customModuleProvider="target" sceneMemberID="viewController">

Использование Xcode 6.3 (6D570), как только я запускаю настройку, возвращается к исходному (плохому). Ошибка? Я пытаюсь включить файл swift в проект Objective C.
addzo

В XCode 6.4 просто добавление customModuleProvider = "target" в исходном коде раскадровки под нужным viewcontroller решило проблему.
Амро Шафи

Я смог решить мою проблему с помощью только что customModule="MyFrameworkName". Огромный +10
Стан

На самом деле моя проблема была в обратном: я хотел удалить CustomTaget, но Xcode не изменял исходный файл xib, поэтому мне пришлось удалить customModule = "AppName" customModuleProvider = "target", чтобы он работал.
Адриана

14

Мой случай - пытаясь использовать класс из быстрой среды в моем проекте c, я получил эту ошибку. Решением было добавить модуль (swift framework) класса в Interface Builder / Storyboard, как показано ниже. Ничего больше

введите описание изображения здесь


2
Я использую фреймворк Swift в проекте Swift, установленном CocoaPods. Этот метод работает. И имя модуля - это имя фреймворка.
JsW

1
Это прекрасно работает. Надо зачем этот модуль убирать ??
iSrinivasan27

Прекрасно работает с проблемами в рамках Cocoapod ... Слава вам за идеальный ответ ...
Jayant Rawat

13

Перейдите в Build Phases-> Compile Sources и добавьте ваши новые .m файлы.


Да, после добавления новых файлов из предыдущего проекта в проект XCode 4.5, добавление файлов .m в список источников компиляции сделало это наверняка. Добавление -all_load -ObjC в моем случае не сработало, хотя и не повредило.
Whyoz

13

В моем случае это показало ошибку для класса, который даже не существовал! Я подозревал, что это было что-то запутанное в файле раскадровки. Если вы не можете распознать файл класса в ошибке, попробуйте это:

1) открыть свой проект в возвышенном или другом хорошем редакторе. Поиск класса, на который ссылаются. 2) удалить весь бит, который говорит

customClass="UnrecognizedClassName"

3) сохранить его. 4) вернитесь в xcode, очистите проект и попробуйте запустить его сейчас.

работал на меня.

введите описание изображения здесь


Я использую приложение OSX TextEdit. Это работало нормально для этой операции. Не забудьте сначала закрыть свой проект и закрыть Xcode.
TJ

Это тоже помогло. У меня было несколько объектов с одним и тем же customClass, я, вероятно, щелкнул представление вместо контроллера и присвоил одно и то же имя.
Mc-

1
Это было также решением проблемы, с которой я столкнулся; Ранее я ввел частичное имя класса, и каким-то образом раскадровка была сохранена таким образом (например customClass="MyCla"). Вместо того, чтобы удалять пользовательское назначение класса, для меня было бы разумно просто поместить класс, который я собирался использовать в первую очередь :)
Дейв

9

Я просто хочу добавить этот ответ, так как большинство, если не все ответы здесь предполагают, что класс действительно существует ... просто компоновщик / компилятор слишком туп, чтобы его увидеть ... таким образом, ответы вращаются вокруг либо оповещения компоновщика о существовании класса или создание взлома, чтобы «заставить» существовать это ..

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

решение?

  • Nuke все это! сначала удалите все файлы сборки и т. д., удалив все содержимое в этом каталоге ~ / Library / Developer / Xcode / DerivedData
  • удалить приложение с самого телефона (и очистить содержимое симулятора, если вы используете симулятор)

ты должен быть хорош, чтобы пойти после этого


2
Не могу +1 этого достаточно, исправил мою проблему. Моя проблема была точно такой же, где файл уже был удален, но предупреждение все еще появлялось при компиляции.
Бретт

В раскадровке вы должны заполнить идентификатор. Иногда я пишу это в поле «Класс» (в Identity Inspector) по ошибке. Таким образом, компилятор жалуется по причине, что Класс не существует!
Винсент

9

Лучший способ устранить ошибку: 1) Выбрать файл класса (.m) 2) В разделе « Целевое членство » «проверить» запись имени проекта.


Это работает. Я разрабатывал pod и по какой-то причине команда pod install применяла неправильную цель к одному конкретному файлу класса. Он применялся к пакету ресурсов, который у меня был. Правильный конфиг - Pods- <project-title> - <pod-title>
krosullivan

Это не работает для меня. Целевое членство верно, но ошибка продолжает возникать.
Кокодоко

8

Я исправил это, скопировав текст из моих class.h и .m, удалив эти файлы классов из проекта и создав новые файлы class.h и .m с тем же именем, используя «Добавить файл». Затем я вставил код обратно в новые файлы, и все отлично заработало. Каким-то образом файлы не были связаны правильно, когда они были созданы. Мне не нужно было использовать какие-либо флаги компоновщика после этого.


1
когда я впервые создал файлы, у меня не было .m в конце. Я попытался переименовать файл и добавить его обратно, однако мне все равно пришлось удалить и воссоздать файл, прежде чем xcode был доволен.
Одит

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

1
Это решение также сработало для меня, но я был на 100% уверен, что перед тем, как удалить первый класс (.h + .m), я проверил, что он является частью моей цели. Это не было проблемой для меня. Как и Лора, я просто удалил класс и создал его снова (с другим именем), и он работал нормально, без каких-либо других решений на этой странице.
конец

7

Я, наконец, исправил это, я забыл добавить следующий код в мой файл .m:

@implementation MyTableViewCell

@end

Так что это было вызвано тем, что я сделал заполнитель @interface для своей ячейки таблицы, которая имела соединение с элементом в файле .xib, но есть ошибка в Интерфейсном Разработчике, где если @implementation не указан для класса, это не может найти это.

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

PS По моему опыту, не имеет значения, если имена файлов .h / .m отличаются от имен @interface. У меня есть несколько файлов, содержащих более одного @interface, и они работают нормально.

PPS У меня есть более подробное объяснение того, почему UITableViewCell и UICollectionViewCell вызывают эту ошибку по адресу https://stackoverflow.com/a/22797318/539149 вместе с тем, как выявлять ее во время компиляции с помощью registerClass: forCellWithReuseIdentifier :.


6

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

  • Щелкните правой кнопкой мыши на .xib и выберите Открыть как> Исходный код
  • В этом файле выполните поиск старого делегата приложения и замените его новым.

Открыть как исходный код больше не существует, но вы также можете легко щелкнуть правой кнопкой мыши, Показать в Finder, затем щелкнуть правой кнопкой мыши по файлу и открыть в TextEdit. Конечно, сделайте резервную копию файла, прежде чем вносить какие-либо изменения;)
Скотт Аллен

6

просто добавьте приведенный ниже код при запуске метода appdelegate applicationatoindidfinishlanching, тогда он будет работать нормально

[класс myclass];


5

Я попробовал этот и другие ответы, перечисленные на этом сайте, но ни один из них не отсортировал их для меня. Эти комментарии (с http://www.iphonedevsdk.com/forum/iphone-sdk-development/43330-unknown-class-interface-builder-file.html ) помогли:

После поиска, поиска и поиска я наконец обнаружил имя этого удаленного класса, скрытое в файле. Мне пришлось открыть файлы конструктора интерфейса в X-коде, щелкнув по ним правой кнопкой мыши и выбрав «просмотреть как исходный код». Затем в поисках его придумали

<object class="NSMutableArray" key="dict.values">
<bool key="EncodedWithXMLCoder">YES</bool>
<string>com.apple.InterfaceBuilder.IBCocoaTouchP lu gin</string>
<string>*this was the class name*</string>

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


5

В моем случае у меня есть XCode6, указанный файл класса .m заканчивается в неправильном месте на этапе сборки - он должен был находиться в разделе Источники компиляции , но в конечном итоге вКопировать ресурсы Bundle


Благодаря вам, я начал просматривать список и обнаружил, что мой файл просто отсутствует, вероятно, когда я его создал, я не установил правильные цели
schmru


4

Эта проблема, похоже, не устарела.

У меня была та же проблема с Xcode 8, и я решил ее так же, как smilebot :

  1. Откройте файл раскадровки как «Исходный код» в Xcode:

  2. Найдите класс, на который вы ссылаетесь, и удалите все, что говорит

customClass = "UnrecognizedClassName"

  1. Снова откройте файл раскадровки как «interfacebuilder - storyboard» и перестройте свое приложение.

3

Просто удалите MyClass.m и .h и снова добавьте их в проект - это работа для меня.


3

У меня было «Неизвестный класс favouritesButton в файле Interface Builder», и я нашел его в сцене сборника рассказов, где у рассматриваемой кнопки был фиктивный пользовательский класс «favouritesButton» в поле «Класс» в верхней части инспектора идентификации. Я хотел поместить это значение в следующее поле: Идентификационная метка.

Изменение этого значения на «UIButton» решило проблему.


2

Я столкнулся с этим в Свифте.

Перемещение .xib-файла в папку Base.lproj проекта избавило от этой ошибки.


Спасибо, что поделились этим, но это не решило мою проблему. Вот решение, которое я наконец нашел: stackoverflow.com/a/28760089/456434
Mazyod

2
Я тоже столкнулся с этой проблемой. Но в моем случае проблема с отсутствующим именем модуля: см. < Stackoverflow.com/a/29013058/784318 >
Besi

1

У меня была эта ошибка, возникающая сегодня при преобразовании моего приложения aaLuminate в Universal под Xcode 4. Это приложение основано на шаблоне утилиты и изначально было построено под Xcode 3.

Чтобы сэкономить время, я скопировал iPhone Main и Flipside Views в соответствующие имена в приложении Universal. Возникла ошибка «Неизвестный класс x в файле Interface Builder». В моем случае ничего не было в файлах или целях XIB.

Я также скопировал файл aaLuminate-Info.plist по другим причинам - для него использовался старый ключ «Основное имя файла пера», установленный в MainWindow.

Как только я удалил этот ключ, это решило проблему!


1

В моем случае я получил эту ошибку, потому что пытался сохранить некоторую работу, создав новый проект, а затем удалив несколько исходных файлов и скопировав исходные файлы с тем же именем из рабочего проекта. Я также скопировал файл MainStoryBoard, который искал мой RootViewController. Однако когда я удалил исходный RootViewController, а затем добавил его в RootViewController из предыдущего продукта, очевидно, что операция «Добавить файлы» не смогла «поставить галочку» в целевом поле, как предложено выше. Просто просмотрев все импортированные файлы ".m" из newley и убедившись, что установлен флажок целевого членства, все было хорошо. Я думаю, что происходило то, что файл раскадровки искал класс, который был «исключен» из ссылки, потому что целевое членство не было проверено. Удостоверившись, что требуемые файлы для цели так обозначены в целевом членстве в файловом инспекторе, сделали свое дело. Спасибо, Пэт! (см. выше)


1

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

не забудьте реализовать любой подкласс подкласса, который вы объявляете в файле .h! Звучит просто, но легко забыть, потому что Xcode сделает это за вас, если вы работаете с одним классом на файл .h / .m.


1

У меня был «Неизвестный класс RateView в Интерфейсном Разработчике», где RateView был подклассом UIView. Я поместил UIView на сцену раскадровки и изменил поле Пользовательский класс на RateView. И все же эта ошибка появилась.

Для отладки я изменил имя своего класса на RateView2 и изменил все ссылки на совпадения, кроме поля Пользовательский класс в UIView. Сообщение об ошибке все еще появлялось как прежде с RateView как отсутствующий класс. Это подтвердило, что сообщение об ошибке было связано со значением поля Пользовательский класс. Я изменил это значение на RateView2, а сообщение об ошибке изменилось на «Неизвестный класс RateView2 в Интерфейсном Разработчике». Прогресс сортов.

Наконец, я проверил сами файлы исходного кода в File Inspector. Там я обнаружил, что файл исходного кода (который я скопировал из учебника) не был связан с моей целью. Другими словами, у него не было целевого членства. Я установил флажок, который сделал файл исходного кода класса членом целевого приложения, и сообщение об ошибке исчезло.


1

В моем случае я удалил класс под названием viewController, не осознавая, что он был выбран с помощью инспектора идентификации раскадровки (в разделе «Пользовательский класс» вверху).

Вам просто нужно просто выбрать правильный класс для контроллера представления в поле Custom Class вашего инспектора идентификации или добавить новый класс в ваш проект и выбрать тот в качестве вашего Custom Class.

Работал на меня!



1

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

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.