usar query persistencia objective example datos data cuando coredata xcode core-data migration string

xcode - query - swift 4 coredata



CoreData: no se puede establecer una cadena vacĂ­a como valor predeterminado para el atributo (7)

Tengo una entidad en mi modelo de datos con un atributo de cadena que actualmente es opcional, y me gustaría convertir esto en un atributo obligatorio con un valor predeterminado de la cadena vacía.

Como otros han descubierto, dejar el valor predeterminado en blanco en el modelador de datos Xcode CoreData da como resultado errores de validación (ya que el diseñador interpreta esto como NULL), pero tratando de '''', "'', o @'' ''como el valor predeterminado da como resultado esos literal los caracteres se interpretan como el predeterminado, en lugar de la cadena vacía de longitud cero, como se desee.

Encontré este hilo en Google, sin embargo, aparte de que la solución es realmente fea (la definición del modelo se divide entre el modelo .xcdata y la fuente objc), tampoco funciona para las migraciones livianas porque esas migraciones se realizan únicamente en base al modelo .xcdata archivos y la lógica objc de las implementaciones de su entidad no está cargado.

¿Hay alguna forma de lograr esto en el diseñador de modelo de datos?


Aquí está la solución de Swift basada en la respuesta de David Ravetti y el comentario de edelaney05. Además, agregué verificación de opcionalidad.

Esta solución funciona bien en mis proyectos.

class ExampleEntity: NSManagedObject { ... override func awakeFromInsert() { super.awakeFromInsert() for (key, attr) in self.entity.attributesByName { if attr.attributeType == .stringAttributeType && !attr.isOptional { if self.value(forKey: key) == nil { self.setPrimitiveValue("", forKey: key) } } } } ... }


Esta es una pregunta muy interesante. Después de algunas pruebas, no creo que esto sea posible debido a la forma en que se configura el campo de texto en el modelo de datos.

En principio, puede usar el carácter de conjunto vacío de /u2205 para representar una cadena vacía predeterminada, pero el campo de texto no parece aceptar ningún escape, por lo que convierte cualquier intento de escape de un código de carácter Unicode en la cadena literal del código los propios caracteres, por ejemplo, ingresando ''/ u2205'' termina como el texto literal ''/ u2205''.

En teoría, podría escribir una aplicación de utilidad para leer en el archivo de modelo de objeto gestionado generado gráficamente y luego establecer programáticamente el valor por defecto del atributo para que sea igual a una cadena vacía y luego guardar el archivo nuevamente en el disco. Digo "en teoría" porque no hay una forma documentada de guardar un archivo de modelo de objeto administrado desde el código. Puede leer uno y modificarlo en la memoria, pero no persistir en los cambios.

Un poco de supervisión, creo.

No creo que tenga otra opción que establecer la cadena vacía predeterminada pragmáticamente cuando el modelo se carga por primera vez. Eso es simple de hacer, pero es feo y tendrás que recordar que lo hiciste (especialmente si migras versiones) pero creo que esa es la única opción.


Mi enfoque para resolver este problema fue crear una subclase NSManagedObject y manejar la sustitución de cadenas vacías por valores NULL en awakeFromInsert . A continuación, configuro todas las entidades como NSManagedObject de esta subclase en lugar de como elementos NSManagedObject de NSManagedObject . La suposición aquí es que quiero que cada atributo de cadena dentro de una entidad determinada se establezca en una cadena vacía por defecto (no funcionaría, o al menos requeriría una lógica adicional, si quisiera que algunos permanezcan NULL dentro de la misma entidad) .

Probablemente exista una manera más eficiente de hacerlo, pero como solo se recurre a la creación de entidades, no creo que sea demasiado exitoso para el rendimiento.

- (void)awakeFromInsert { [super awakeFromInsert]; NSDictionary *allAttributes = [[self entity] attributesByName]; NSAttributeDescription *oneAttribute; for (NSString *oneAttributeKey in allAttributes) { oneAttribute = [allAttributes objectForKey:oneAttributeKey]; if ([oneAttribute attributeType] == NSStringAttributeType) { if (![self valueForKey:[oneAttribute name]]) { [self setValue:@"" forKey:[oneAttribute name]]; } } } }


Puedes hacerlo manualmente En su clase de modelo, anule awakeFromInsert y establezca sus cadenas en string vacío

Rápido:

override func awakeFromInsert() { super.awakeFromInsert() self.stringProperty = "" }

C objetivo

- (void) awakeFromInsert { [super awakeFromInsert]; self.stringProperty = @""; }


Resolví esto anulando el getter para mi campo; si contiene null, devuelvo una cadena vacía en su lugar:

-(NSString *)unit { if ([self primitiveValueForKey:@"unit"] == NULL) { return @""; } else { return [self primitiveValueForKey:@"unit"]; } }

Hasta ahora, parece estar haciendo el truco, y me imagino que no afectaría las migraciones (aunque no sé lo suficiente sobre ellos para decirlo con certeza). Realmente no me importa si hay una cadena vacía o nula en el DB, después de todo, siempre que obtenga "" en lugar de nulo cuando solicite el campo.


Saca tu editor XML favorito (yo solo uso Emacs) y .xcdatamodel al archivo de contents dentro del paquete .xcdatamodel dentro del paquete .xcdatamodeld . A continuación, simplemente agregue un valor defaultValueString="" al elemento <attribute>...</attribute> dentro de los corchetes <entity>...</entity> . Aquí hay un ejemplo:

<attribute name="email" attributeType="String" defaultValueString="" syncable="YES"/>

No puedo decir si esto sobrevive a la migración ya que no he tenido que hacerlo todavía.


Tal vez llego tarde con esta respuesta, pero estaba buscando en Google y encontré este foro.

La solución es muy simple:

  1. Cuando hace clic en xcdatamodelId (En la pantalla de la izquierda)
  2. Cambiar la vista de entidad a gráfico
  3. Haga doble clic en cualquier atributo que desee y el menú aparecerá a la derecha.

Todos los cambios son fáciles.

Parte 2

Parte 3