Xcode 8 генерирует разбитые подклассы NSManagedObject для iOS 10
Недавно я обновил проект приложения iOS для iOS 10. Теперь я пытаюсь изменить модель основных данных моего приложения, но новые подклассы NSManagedObject, которые генерируются Xcode, нарушены. Я также попытался исправить руководство к подклассам, но это не сработало.
Минимальная версия инструментов для Core Data Model установлена на Xcode 7.0, а язык генерации кода - на Swift.
Это код, который генерирует Xcode:
import Foundation
import CoreData
import
extension Group {
@nonobjc public class func fetchRequest() -> NSFetchRequest {
return NSFetchRequest(entityName: "Group");
}
@NSManaged public var name: String?
@NSManaged public var platform: NSNumber?
@NSManaged public var profiles: NSOrderedSet?
}
// MARK: Generated accessors for profiles
extension Group {
@objc(insertObject:inProfilesAtIndex:)
@NSManaged public func insertIntoProfiles(_ value: SavedProfile, at idx: Int)
@objc(removeObjectFromProfilesAtIndex:)
@NSManaged public func removeFromProfiles(at idx: Int)
@objc(insertProfiles:atIndexes:)
@NSManaged public func insertIntoProfiles(_ values: [SavedProfile], at indexes: NSIndexSet)
@objc(removeProfilesAtIndexes:)
@NSManaged public func removeFromProfiles(at indexes: NSIndexSet)
@objc(replaceObjectInProfilesAtIndex:withObject:)
@NSManaged public func replaceProfiles(at idx: Int, with value: SavedProfile)
@objc(replaceProfilesAtIndexes:withProfiles:)
@NSManaged public func replaceProfiles(at indexes: NSIndexSet, with values: [SavedProfile])
@objc(addProfilesObject:)
@NSManaged public func addToProfiles(_ value: SavedProfile)
@objc(removeProfilesObject:)
@NSManaged public func removeFromProfiles(_ value: SavedProfile)
@objc(addProfiles:)
@NSManaged public func addToProfiles(_ values: NSOrderedSet)
@objc(removeProfiles:)
@NSManaged public func removeFromProfiles(_ values: NSOrderedSet)
}
Изменить: это конкретные ошибки, которые Xcode дает:
1. Group+CoreDataProperties.swift:13:1: Expected identifier in import declaration (the empty import)
2. Group+CoreDataProperties.swift:13:11: 'Group' is ambiguous for type lookup in this context
3. Group+CoreDataProperties.swift:15:16: Cannot specialize non-generic type 'NSFetchRequest'
4. Group+CoreDataProperties.swift:26:11: 'Group' is ambiguous for type lookup in this context
4. Group+CoreDataProperties.swift:43:82: 'SavedProfile' is ambiguous for type lookup in this context
Ответы
Ответ 1
Наконец-то я получил работу. Вот что я сделал. (Полеты - одно из моих сущностей)
Я устанавливаю xcdatamodeld следующим образом
![введите описание изображения здесь]()
И затем объект как
![введите описание изображения здесь]()
Затем я использовал Editor → Create NSManagedObject Subclass
Это создает два файла для моего объекта полета
Авиабилеты + CoreDataProperties.swift
Авиабилеты + CoreDataClass.swift
Я переименовал рейсы + CoreDataClass.swift в Flight.swift
Авиабилеты .swift просто
import Foundation
import CoreData
@objc(Flights)
public class Flights: NSManagedObject {
}
Полеты + CoreDataProperties.swift
import Foundation
import CoreData
extension Flights {
@nonobjc public class func fetchRequest() -> NSFetchRequest<Flights> {
return NSFetchRequest<Flights>(entityName: "Flights");
}
@NSManaged public var ...
}
Это, похоже, работает для меня. Я не мог заставить Codegen работать каким-либо другим образом, хотя я пробовал много предложений, которые были там.
И это заставило меня немного почесывать голову, и я добавляю ее в качестве помощи. Не забывайте, что в новой версии Generics FetchRequest вы можете сделать это
let fetchRequest: NSFetchRequest<NSFetchRequestResult> = NSFetchRequest(entityName: "Flights")
Ответ 2
Я полагаю, что причина, по которой вы столкнулись с этими ошибками после создания файлов подкласса NSManagedObject, может быть связана с параметром Codegen, который был выбран в то время, когда изменилась ваша модель данных.
Я не думаю, что это ошибка. По крайней мере, не в Xcode 8.1 (8B62).
Я столкнулся с подобной проблемой и исправил ее, изменив параметр Codegen на "Manual/None" и оставив параметр Module "Global Namespace". Затем я сгенерировал файлы подкласса NSManagedObject. Однако, в зависимости от вашей ситуации, вам даже не нужно создавать подклассы NSManagedObject.
Ниже приведены более подробные сведения об объектах Codegen, основанных на моем обзоре документации Apple, форуме разработчиков Apple и тестировании с помощью моего собственного проекта.
Вариант 1: "Определение класса"
-
Подумайте об этом как о опции "plug and play"
-
Используйте редактор модели для создания сущностей и связанных атрибутов
что вы хотите управлять основными данными.
-
Не используйте генератор подкласса NSMangagedObject. Требуемый
файлы автоматически генерируются для вас Xcode (однако они
не отображается в вашем навигаторе проекта).
-
Если вы создаете файлы NSManagedObject, Apple сообщает вам, что
эти файлы не должны редактироваться в комментариях заголовка указанного
файлы. Если вам нужно отредактировать эти файлы, тогда это хороший знак
что вам нужно использовать другой вариант Codegen.
-
Оставьте параметры класса по умолчанию для вашего объекта (Module = Global
Пространство имен и Codegen = Определение класса)
-
Если вам необходимо переопределить методы NSManagedObject, вы можете
создайте расширение с помощью параметра "Имя под классом".
// Optional extension in Entity.swift
extension Entity {
// Override NSManagedObject methods
}
Опции 2: "Руководство/Нет"
-
Аналогично варианту 1, за исключением того, что вы можете видеть и редактировать
Файлы подкласса NSManagedObject.
-
Используйте редактор модели для создания сущностей и связанных атрибутов
что вы хотите управлять основными данными.
-
Перед использованием генератора подкласса NSManagedObject установите Codgen
вариант "Ручной/Нет" для объекта. Опция модуля должна быть
Глобальное пространство имен.
-
После добавления/удаления/обновления атрибута у вас есть два варианта: (1)
Вручную обновите файлы NSManagedObject, которые были сгенерированы для вас
ИЛИ (2) Повторно используйте генератор подкласса NSManagedObject (это будет
только обновить файл Entity + CoreDataProperties.swift).
-
Опять же, если вам нужно переопределить и методы из NSManagedObject, вы
может создать расширение. Расширение должно быть создано в
Entity + CoreDataClass.swift, а не
Файл Entity + CoreDataProperties.swift(этот файл может быть обновлен из-за
для изменения параметров редактора).
// Optional extension in Entity+CoreDataClass.swift
extension Entity {
// Override NSManagedObject methods
}
Вариант 3: "Категория/Расширение"
-
Используйте этот параметр, если у вас есть настраиваемые свойства, которые не должны быть
управляемый Core Data.
-
Используйте редактор модели для создания сущностей и связанных атрибутов
что вы хотите управлять основными данными.
-
Убедитесь, что для параметра "Модуль" установлено значение "Текущий модуль продукта" и
Параметр Codegen имеет значение "Категория/Расширение".
-
Создайте свой собственный подкласс NSManagedObject со свойствами, которые вы
будет управлять собой.
-
Не используйте генератор подкласса NSMangagedObject. Требуемый
файлы автоматически генерируются для вас Xcode (однако они
не отображается в вашем навигаторе проекта).
// Subclass NSManagedObject in Entity.swift
class Entity: NSManagedObject {
// Self managed properties
}
// Optional extension in Entity.swift
extension Entity {
// Override NSManagedObject methods
}
Ответ 3
-
Чтобы решить эту проблему, удалите полученные данные приложения.
-
Затем измените Модуль на Текущий модуль продукта, а также внесите изменения в Codegen на Ручной/Нет.
-
![Элемент списка]()
Ответ 4
Попробуйте установить CodeGen: Manual/None
Модуль: текущий модуль продукта
Это сработало для меня хорошо, когда я столкнулся с той же проблемой.
![введите описание изображения здесь]()
Ответ 5
Вы можете попробовать выполнить следующие действия.
- Выберите файл .xcdatamodeld в Навигаторе проектов Xocde
- В Data Modul Inspector убедитесь, что Codegen: Ручной/Нет
- Затем Изменить → Создать подкласс NSManagedObject
- Очистить продукт и перестроить
Это работа? Если не
Убедитесь, что у всех классов нет одинакового имени с Сущностями. Вы можете найти этот класс в Фазах сборки → Скомпилировать источники. Переименуйте класс или объекты, если они дублируются.
или
Вы можете запустить эту команду в своей папке проекта, чтобы получить дополнительную информацию об ошибке
xcodebuild -verbose
Я получил это сообщение, когда у меня возникла эта проблема
дублировать символ _OBJC_CLASS _ $_ RandomList в:
xxxx/RandomList.o
хххх/RandomList + CoreDataClass.o
RandomList.h и RandomList + CoreDataClass.h имеют один и тот же символ при компиляции
Я думаю, что почему Xcode не предупреждал вас, но компилятор будет вызывать ошибку
Надеюсь, это поможет вам
Ответ 6
Если у вас есть устаревшее приложение, и вы хотите вручную добавлять классы управляемых объектов
- Убедитесь, что для вашей основной модели данных в кодеге установлено значение Ручное/Нет
- Выберите файл основной модели данных
- Создание подкласса управляемого объекта
![скриншот редактора]()
Ответ 7
Удалить третий оператор import
, потому что он пуст.
Примечание. Я не знаю, почему это происходит, но я думаю, что это ошибка в Xcode 8. Просто удалите ее, и она будет работать нормально.
Ответ 8
На Xcode 8.2.1 я сделал так: (спасибо за Даниеля Чепенко)
![enter image description here]()
Но Xcode 8.2.1 добавит глупость . в сгенерированные файлы:
![enter image description here]()
Просто удалите . и он будет работать правильно.
Ответ 9
У меня просто была проблема, когда я просто добавил объект Person в моей модели к шаблону Core Data. Затем сгенерирован подкласс NSManagedObject для этого, и он не будет компилироваться, что даст мне ошибку Linker. Оказывается, я должен изменить параметр Codegen на Manual/None, чтобы он работал (см. Нижнюю правую часть изображения). ![введите описание изображения здесь]()
Ответ 10
Я думаю, что это проблема с xcode, где xcode генерирует неправильный синтаксис для класса категории основных данных.
Я создаю nsmanageobjectsubclass
для одного объекта AgentDetails
![Он создает следующие классы]()
Здесь xcode создает неправильную структуру кода в AgentDetails+CoreDataClass.h
и AgentDetails+CoreDataClass.m
. У них есть структура кода, например:
![введите описание изображения здесь]()
И
![введите описание изображения здесь]()
Таким образом, он имеет проблему с дублирующимся интерфейсом, поскольку AgentDetails.h
имеет один и тот же интерфейс.
Теперь, чтобы исправить это, вы должны изменить код в AgentDetails+CoreDataClass.h
![введите описание изображения здесь]()
и AgentDetails+CoreDataClass.m
следующим образом:
![введите описание изображения здесь]()
Ответ 11
В Data Model Inspector выберите "Текущий модуль продукта" в разделе "Модуль" и "Ручной/Нет" в разделе "Кодекен". (Это позволяет редактировать файлы подкласса и регенерировать CoreDataProperties.swift, когда вы изменяете свои атрибуты под одним и тем же объектом.)
![введите описание изображения здесь]()
Затем вы можете выбрать "Создать NSManagedObjectSubclass" в меню "Редактор". Xcode создаст вам 2 файла YourEntity + CoreDataClass.swift и YourEntity + CoreDataProperties.swift. Обратите внимание, если у вас нет последнего Xcode (8.2.1), любые необязательные/неопытные свойства, которые вы задали в вашем инспекторе моделей, не будут отображаться правильно. Вы можете редактировать
Файл YourEntity + CoreDataProperties.swift.
Ответ 12
Xcode 8.1, по-видимому, создает класс модели внутри. Просто удалите созданные 2 класса, и вы все равно сможете использовать сущности в вашем коде.
Здесь сообщение об ошибке, которое я получал
<unknown>:0: error: filename "Recipe+CoreDataProperties.swift" used twice: '/Users/Rick/Desktop/Devslop/Rick Recipe/Recipe+CoreDataProperties.swift' and '/Users/Rick/Library/Developer/Xcode/DerivedData/Rick_Recipe-cctgjudvqobxlwetbcwmzrgxigwg/Build/Intermediates/Rick Recipe.build/Debug-iphonesimulator/Rick Recipe.build/DerivedSources/CoreDataGenerated/Rick_Recipe/Recipe+CoreDataProperties.swift'
<unknown>:0: note: filenames are used to distinguish private declarations with the same name
Command /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swiftc failed with exit code 1
Ответ 13
Кроме того, если вы добавляете подкласс NSManagedObject самостоятельно, не забудьте выполнить следующий шаг:
Перейдите в ".xcdatamodeld" → Выберите объект → Показать инспектор модели данных → Codegen → Выберите "Руководство/Нет"
Это сработало для меня.
Ответ 14
Я нашел эту Сообщение от Дэвида Аткинсона, которая в какой-то мере помогает.
Если я сгенерирую код так, как описал Дэвид. Я просто получаю код с некоторыми синтаксическими ошибками, и если я исправляю ошибки, все работает как раньше. Отсутствуют файлы, начинающиеся с '.' больше.
Синтаксические ошибки, которые я должен исправить,
- ненужный импорт
- и некоторые общедоступные свойства, которые не предназначены для публикации в моем коде
Ответ 15
Я запускаю последнюю версию бета-версии Xcode 8.1 (8T47).
В соответствии с журналом ошибок (см. ниже) создаются две копии автогенерированных файлов. Один экземпляр помещается в папку проекта Xcode (тот, который отображается в вашем каталоге на левой панели инструментов Xcode), а вторая копия создается в вашей папке DerivedData для вашего проекта:
/Users/<your name>/Library/Developer/Xcode/DerivedData/<your app>-axhtnodotznxnrenefflktnxfeal/Build/Intermediates/<your app>.build/Debug-iphonesimulator/<your app>.build/DerivedSources/CoreDataGenerated/<your app>/<class name>+CoreDataProperties.swift
/Users/<your name>/Library/Developer/Xcode/DerivedData/<your app>-axhtnodotznxnrenefflktnxfeal/Build/Intermediates/<your app>.build/Debug-iphonesimulator/<your app>.build/DerivedSources/CoreDataGenerated/<your app>/<class name>+CoreDataClass.swift
Удаление копий в каталоге проекта Xcode устранит все проблемы, но окажется бессмысленным, поскольку вы больше не можете редактировать эти файлы...
Я бы не сказал, что это решение, а всего лишь полуподобный способ создания проекта. Надеемся, что эта ошибка будет решена в ближайшее время.
![Журнал ошибок]()
Ответ 16
Для меня я создал классы CocoaTouch путем подкласса NSManagedObject
вручную. Я установил модуль как Current Product Module и Codegen как Category/Extension, и он работает хорошо.
Ответ 17
В моем конкретном случае я добавил CoreData в существующий проект, который уже имел класс Model с тем же именем, что и моя сущность. Удаление старого класса Model решило проблему, так как его тип сталкивался с новым классом CoreData Entity.
Ответ 18
Я кладу зерно соли, учитывая, что я вижу много ответов, которые решают проблему, но у меня нет реальной причины того, что действительно происходит здесь.
Я наткнулся на эту самую проблему, и, проведя быстрое исследование, я смог обнаружить, что:
-
До Xcode 7 поведение по умолчанию для сущности Core Data заключалось в том, что разработчику приходилось вручную создавать и поддерживать изменения соответствующих подклассов NSManagedObject. (Это можно и можно сделать, используя меню редактора, выбрав опцию "Создать подкласс NSManagedObject...").
-
Начиная с Xcode 8, Apple включила новый параметр прямо в инспектор модели данных с именем Codegen для управления и поддержки подклассов NSManagedObject. Значением по умолчанию для этого параметра является "Определение класса", которое сообщает XCode генерировать подклассы NSManagedObject на основе наших определенных объектов во время компиляции и помещать их в папку производных данных.
Наличие в проекте наших подклассов NSManagedObject + те, которые Xcode генерирует автоматически, приводят нас к реальной причине ошибки времени компиляции "Несколько команд создают...", поскольку теперь у нас есть дублированные модели управляемых объектов !!!
Решение тогда состоит в том, чтобы использовать то или другое, а не оба! Я лично предпочитаю, чтобы мои модели управляемых объектов были включены в проект, поэтому я изменил настройку "Codegen" на "Manual/None". Если вы не добавляете логику к моделям, держу пари, вы можете отказаться, удалив модели управляемых объектов вашего проекта, и позволить XCode делать свое дело на основе значения "Определение класса" для упомянутой настройки. Это правильный способ справиться с этой проблемой.
Вы можете найти отличную статью, объясняющую все это подробно здесь:
https://medium.com/@kahseng.lee123/core-data-codegen-explained-462c30341041
Ответ 19
Я решил это как пример, приведенный ниже
Создать CurrentcyPair.xcdatamodeld
выберите CurrentcyPair.xcdatamodeld и выберите Default → Entity (CurrencyPair), переименуйте класс в (.ManagedCurrencyPair)
Выберите Entity и откройте инспектора. Установить код поколения в модели данных как Ручной/Нет
![enter image description here]()
![enter image description here]()
Ответ 20
Что вам нужно сделать, это установить CodeGen в категорию/расширение, прежде чем выполнять подклассы Create NSManagedObject.
Ответ 21
У меня есть объект "Полеты", и эти настройки в Data Model Inspector работали для меня:
-
Задайте имя никому (вы увидите некоторый текст с серым цветом "NSManagedObject" ). Значение по умолчанию будет записано как "Полеты", просто удалите это.
-
Ничего в модуле. "Глобальное пространство имен" greyed out - это то, что вы увидите.
-
Codegen to Manual/None.
-
Затем нажмите "Редактор" → Создать подкласс NSManagedObject для создания быстрых файлов
-
Переименуйте полеты + CoreDataClass.swift только на рейсы .swift
Здесь ссылка на скриншот (по какой-то причине imgur отклонил это:() https://drive.google.com/file/d/0B8a3rG93GTRedkhvbWc5Ujl4Unc/view?usp=sharing
Ответ 22
После того как я переименовал следующее:
От: YourEntity + CoreDataClass.swift To: YourEntity.swift
и
От: YourEntity + CoreDataProperties.swift To: YourEntityCoreDataProperties.swift
тогда он работает. Похоже, что проблема "+" вызывает проблему.