core data - Xcode 8 genera subclases de NSManagedObject rotas para iOS 10
core-data ios10 (22)
Recientemente actualicé mi proyecto de aplicación de iOS a iOS 10. Ahora estoy tratando de cambiar el Modelo de datos básicos de mi aplicación, pero las nuevas subclases de NSManagedObject que genera Xcode están rotas. También intenté arreglar el manual de subclases pero esto no funciona.
La versión de herramientas mínimas para el Core Data Model está establecida en Xcode 7.0 y el lenguaje de generación de código está configurado en Swift.
Este es el código que genera 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)
}
Editar: Estos son los errores específicos que da 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
Acabo de tener un problema en el que acabo de agregar una entidad Persona en mi modelo a la plantilla Core Data. Luego generó la subclase NSManagedObject para eso y no se compilará, dándome un error de vinculador. Resulta que se supone que debo cambiar la opción Codegen a Manual / Ninguno para que funcione (vea la parte inferior derecha de la imagen).
Además, si agrega la subclase NSManagedObject usted mismo, no olvide seguir el siguiente paso: Vaya a ''.xcdatamodeld'' -> Elija la entidad -> Mostrar inspector de modelo de datos -> Codegen -> Elija ''Manual / Ninguno''
Esto funcionó para mí.
Creo que es un problema de xcode, donde xcode genera una sintaxis incorrecta para la clase de categoría de datos principales.
Estoy creando una
nsmanageobjectsubclass
para una entidad
AgentDetails
Aquí xcode crea una estructura de código incorrecta en
AgentDetails+CoreDataClass.h
y
AgentDetails+CoreDataClass.m
.
Esos tienen una estructura de código como:
Y
Por lo tanto, está teniendo un problema de interfaz duplicada ya que
AgentDetails.h
tiene la misma interfaz.
Ahora para solucionar esto, debe cambiar el código en
AgentDetails+CoreDataClass.h
y
AgentDetails+CoreDataClass.m
así:
Creo que la razón por la que encontró esos errores después de generar los archivos de la subclase NSManagedObject puede estar relacionada con la opción Codegen que se seleccionó en el momento en que cambió su modelo de datos.
No creo que esto sea un error. Al menos no en Xcode 8.1 (8B62).
Encontré un problema similar y lo solucioné cambiando la opción Codegen a "Manual / Ninguno" y dejando la opción Módulo como "Espacio de nombres global". Luego generé mis archivos de subclase NSManagedObject. Sin embargo, dependiendo de su situación, es posible que ni siquiera necesite generar las subclases NSManagedObject.
A continuación se presentan más detalles sobre las opciones de Codegen de la entidad basadas en mi revisión de la documentación de Apple, el foro de desarrolladores de Apple y las pruebas con mi propio proyecto.
Opción 1: "Definición de clase"
-
Piense en esto como la opción "plug and play"
-
Use el editor de modelos para crear las entidades y los atributos asociados que desea que Core Data administre.
-
No utilice el generador de subclase NSMangagedObject. Xcode genera automáticamente los archivos necesarios para usted (sin embargo, no se muestran en el navegador del proyecto).
-
Si genera los archivos NSManagedObject, Apple le dice que estos archivos no deben editarse en los comentarios del encabezado de dichos archivos. Si necesita editar estos archivos, esta es una buena señal de que necesita usar otra opción de Codegen.
-
Deje las opciones de clase predeterminadas para su entidad (Módulo = Espacio de nombres global y Codegen = Definición de clase)
-
Si necesita anular los métodos del NSManagedObject, puede crear una extensión usando el Nombre debajo de la opción Clase.
// Optional extension in Entity.swift extension Entity { // Override NSManagedObject methods }
Opciones 2: "Manual / Ninguno"
-
Similar a la Opción 1, excepto que puede ver y editar los archivos de la subclase NSManagedObject.
-
Use el editor de modelos para crear las entidades y los atributos asociados que desea que Core Data administre.
-
Antes de usar el generador de subclases NSManagedObject, configure la opción Codgen en "Manual / Ninguno" para la entidad. La opción Módulo debería ser Espacio de nombres global.
-
Después de agregar / eliminar / actualizar un atributo, tiene dos opciones: (1) Actualizar manualmente los archivos NSManagedObject que se generaron para usted O (2) Usar el generador de subclase NSManagedObject nuevamente (esto solo actualizará el archivo Entity + CoreDataProperties.swift )
-
Nuevamente, si necesita anular y métodos de NSManagedObject, puede crear una extensión. La extensión debe crearse en el archivo Entity + CoreDataClass.swift y no en el archivo Entity + CoreDataProperties.swift (este archivo podría actualizarse debido a cambios en el editor del modelo).
// Optional extension in Entity+CoreDataClass.swift extension Entity { // Override NSManagedObject methods }
Opción 3: "Categoría / Extensión"
-
Use esta opción si tiene propiedades personalizadas que no necesitan ser administradas por Core Data.
-
Use el editor de modelos para crear las entidades y los atributos asociados que desea que Core Data administre.
-
Asegúrese de que la opción Módulo esté establecida en Módulo de producto actual y la opción Codegen esté establecida en "Categoría / Extensión".
-
Cree su propia subclase de NSManagedObject con las propiedades que administrará usted mismo.
-
No utilice el generador de subclase NSMangagedObject. Xcode genera automáticamente los archivos necesarios para usted (sin embargo, no se muestran en el navegador del proyecto).
// Subclass NSManagedObject in Entity.swift class Entity: NSManagedObject { // Self managed properties }
// Optional extension in Entity.swift extension Entity { // Override NSManagedObject methods }
Después cambié el nombre de lo siguiente:
De: YourEntity + CoreDataClass.swift Para: YourEntity.swift
y
De: YourEntity + CoreDataProperties.swift Para: YourEntityCoreDataProperties.swift
entonces funciona Parece que "+" está causando el problema.
Elimine la tercera declaración de
import
porque está vacía.
Nota: No sé por qué sucede esto, pero supongo que es un error en Xcode 8. Simplemente elimínelo y funcionará bien.
En el Inspector del modelo de datos, seleccione Módulo del producto actual en ''Módulo'' y Manual / Ninguno en ''Codegen''. (Esto le permite editar archivos de subclase y regenerar CoreDataProperties.swift cuando modifica sus atributos bajo la misma entidad).
Luego puede elegir Crear NSManagedObjectSubclass en el menú Editor. Xcode creará 2 archivos para usted YourEntity + CoreDataClass.swift y YourEntity + CoreDataProperties.swift. Tenga en cuenta que si no tiene el último Xcode (8.2.1), las propiedades opcionales / no opcionales que establezca en su Inspector de modelos no se mostrarán correctamente. Puede editar en el archivo YourEntity + CoreDataProperties.swift.
En mi caso particular, había agregado CoreData a un proyecto existente que ya tenía una clase Model con el mismo nombre que mi entidad. La eliminación de la antigua clase Modelo solucionó el problema, ya que su tipo colisionaba con la nueva clase CoreData Entity.
Encontré esta publicación de David Atkinson que es útil de alguna manera. Si genero el código como David lo describió. Acabo de recibir el código con algunos errores de sintaxis y si soluciono los errores todo funciona como antes. No faltan archivos que comienzan con ''.'' nunca más.
Los errores de sintaxis que tengo que corregir son: la importación innecesaria, y algunas propiedades públicas que no están destinadas a ser públicas en mi código
Estoy ejecutando la última versión de Xcode 8.1 beta (8T47).
Según el registro de errores (ver más abajo), se crean dos copias de los archivos autogenerados. Se coloca una copia en su carpeta de proyecto Xcode (la que está visible en su directorio en la barra de herramientas del lado izquierdo de Xcode), y se crea una segunda copia en su carpeta DerivedData para su proyecto:
/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
Eliminar las copias en el directorio del proyecto Xcode solucionará todos los problemas, pero no tiene sentido ya que ya no puede editar estos archivos ...
No diría que esta es una solución, sino solo una forma poco convincente de lograr que el proyecto se construya. Esperemos que este error se solucione pronto.
Estoy poniendo mi grano de sal dado que puedo ver muchas respuestas que resuelven el problema, pero me falta la verdadera razón detrás de lo que realmente está sucediendo aquí.
Me topé con este mismo problema y al hacer una investigación rápida pude encontrar que:
-
Hasta Xcode 7, el comportamiento predeterminado para una entidad de Core Data era que el desarrollador tenía que crear y mantener manualmente los cambios de las subclases de NSManagedObject correspondientes. (Esto podría, y aún puede lograrse, haciendo uso del menú del editor seleccionando la opción "Crear subclase NSManagedObject ..").
-
A partir de Xcode 8, Apple ha incluido una nueva configuración en el Inspector del modelo de datos llamada Codegen para administrar y mantener las subclases de NSManagedObject. El valor predeterminado para esta configuración es "Definición de clase", que le dice a Xcode que genere las subclases NSManagedObject basadas en nuestras entidades definidas en tiempo de compilación y las coloque en la carpeta de datos derivados.
Tener nuestras subclases de NSManagedObject dentro del proyecto + las que Xcode genera automáticamente nos lleva a la verdadera razón detrás del error de tiempo de compilación "Múltiples comandos producen ..." ya que ahora tenemos modelos de objetos administrados duplicados.
La solución es usar uno u otro, ¡no ambos! Personalmente prefiero tener mis modelos de objetos administrados dentro del proyecto, así que he cambiado esta configuración de "Codegen" a "Manual / Ninguno". Si no está agregando lógica a los modelos, apuesto a que podría optar por eliminar los modelos de objetos administrados de su proyecto y dejar que Xcode haga lo suyo en función del valor de "Definición de clase" para la configuración mencionada. Esta es la forma correcta de lidiar con este problema.
Puede encontrar un gran artículo que explica todo esto en detalle aquí:
https://medium.com/@kahseng.lee123/core-data-codegen-explained-462c30341041
Finalmente conseguí el mío para trabajar. Aquí esta lo que hice. (Vuelos es una de mis entidades)
Configuré el xcdatamodeld de la siguiente manera
Y luego la entidad como
Luego usé Editor -> Crear subclase de NSManagedObject
Esto crea dos archivos para mi entidad de vuelos
Vuelos + CoreDataProperties.swift
Vuelos + CoreDataClass.swift
Cambié el nombre de Vuelos + CoreDataClass.swift a Flights.swift
Flights.swift es solo
import Foundation
import CoreData
@objc(Flights)
public class Flights: NSManagedObject {
}
Vuelos + CoreDataProperties.swift es
import Foundation
import CoreData
extension Flights {
@nonobjc public class func fetchRequest() -> NSFetchRequest<Flights> {
return NSFetchRequest<Flights>(entityName: "Flights");
}
@NSManaged public var ...
}
Esto parece funcionar para mí. No pude lograr que Codegen funcione de otra manera, a pesar de que probé muchas de las sugerencias que había.
Además, esto me hizo rascarme la cabeza por un tiempo y lo agregué como ayuda. No olvides que con la nueva versión genérica de FetchRequest puedes hacer esto
let fetchRequest: NSFetchRequest<NSFetchRequestResult> = NSFetchRequest(entityName: "Flights")
Lo que debe hacer es establecer CodeGen en Categoría / Extensión antes de ejecutar las subclases Crear NSManagedObject.
Lo resolví como un ejemplo dado a continuación
Crear CurrentcyPair.xcdatamodeld
seleccione CurrentcyPair.xcdatamodeld y seleccione Predeterminado -> Entidad (CurrencyPair), cambie el nombre de la clase como (.ManagedCurrencyPair)
Seleccione Entidad y abra Inspector. Establecer código gen en el modelo de datos como Manual / Ninguno
Para mí, creé las clases CocoaTouch subclasificando
NSManagedObject
manualmente.
Configuré el módulo como Módulo de producto actual y Codegen como Categoría / Extensión y funciona bien.
Puedes probar estos pasos
- Seleccione el archivo .xcdatamodeld en Xocde Project Navigator
- En el Inspector del módulo de datos , asegúrese de Codegen : Manual / None
- Luego Editar -> Crear subclase de NSManagedObject
- Limpiar producto y reconstruir
¿Eso es trabajo? Si no
Asegúrese de que toda la clase no tenga el mismo nombre con Entidades . Puede encontrar estas clases en Fases de compilación -> Compilar fuentes . Cambie el nombre de la clase o las entidades si se duplicaron
O
Puede ejecutar este comando en su carpeta de proyecto para obtener más información de error
xcodebuild -verbose
Recibí este mensaje cuando tengo este problema
símbolo duplicado _OBJC_CLASS _ $ _ RandomList en:
xxxx / RandomList.o
xxxx / RandomList + CoreDataClass.o
RandomList.h y RandomList + CoreDataClass.h tienen el mismo símbolo al compilar
Creo que por eso Xcode no te advirtió, pero el compilador arrojará un error
Espero que esto te ayudará
Tengo una Entidad de vuelos y esta configuración en el Inspector del modelo de datos funcionó para mí:
-
Establezca el Nombre en nada (verá un texto en gris de "NSManagedObject"). El valor predeterminado se escribirá como "Vuelos" simplemente elimine eso.
-
No hay nada en el módulo. "Espacio de nombres global" atenuado es lo que verá.
-
Codegen a Manual / Ninguno.
-
Luego, vaya al Editor -> Crear subclase de NSManagedObject para crear los archivos rápidos
-
Cambie el nombre de Flights + CoreDataClass.swift a solo Flights.swift
Aquí está el enlace a la captura de pantalla (por alguna razón imgur lo rechazó :() https://drive.google.com/file/d/0B8a3rG93GTRedkhvbWc5Ujl4Unc/view?usp=sharing
Xcode 8.1 parece estar generando Model Class internamente. Simplemente elimine las 2 clases creadas y aún podrá usar las entidades en su código.
Aquí está el mensaje de error que recibí
<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