Clave principal de datos principales

81

Esto puede parecer estúpido, pero todavía no pude averiguar cómo marcar un atributo como clave principal en el archivo xcdatamodel. Mi almacenamiento persistente es un archivo sqlite. ¿Alguien puede ayudarme?

En ese caso, ¿cómo puedo "validar" una identificación para que sea única? ¿Debo escribir un método de validación o algo así?

Mugunth
fuente

Respuestas:

91

Tus opciones son:

  • Utilice -[NSManagedObject objectID]. Tenga en cuenta que esta ID es temporal hasta que el objeto se guarde por primera vez o llame-[NSManagedObjectContext obtainPermanentIDsForObjects:error:]
  • Use la CFUUIDfamilia de funciones para generar un UUID para cada objeto en su -awakeFromInsertmétodo
  • Cree su propio sistema similar a una clave primaria que almacena un número entero en su modelo y lo incrementa con la creación de cada objeto

No existe una buena forma de validar que una propiedad sea única. Lo más cercano que obtendrá es asegurarse de que sea único en el momento de la creación y luego implementar un método de establecimiento personalizado que evite que cualquiera cambie la ID.

Mike Abdullah
fuente
5
Una respuesta mucho más constructiva: ¡debería marcarse como la solución!
Grouchal
1
Generar UUID es la mejor manera de hacerlo. Lo estamos usando en nuestra aplicación y está funcionando muy bien.
object2.0
46

Tenga en cuenta que Core Data es un marco de persistencia de gráficos de objetos, no una base de datos. Cosas como las claves primarias se abstraen porque dependen de la implementación del almacén persistente.

Marc Charbonneau
fuente
2
¡Esta debería haber sido la respuesta que debería haber elegido @Mugunth! Gracias por tu conocimiento.
Leonard
Entonces, ¿Core Data solo generará la clave principal por sí solo?
Próximo desarrollador
24

Core Data crea su propia clave principal, no es necesario que agregue una. Puedes recuperarlo con

NSManagedObjectID *moID = [managedObject objectID];
Paul Tomblin
fuente
14

a veces, al piratear, se necesita el int real de la clave principal. así es como uno puede agarrarlo:

NSManagedObjectID *yourManagedObjectID = [yourManagedObject objectID];
int yourManagedObject_PK = [[[[[yourManagedObjectID URIRepresentation] absoluteString] lastPathComponent] substringFromIndex:1] intValue];

a pesar de que CoreData es un gráfico de objetos, si uno mira los datos de la base de datos SQLite generados por CoreData, esta forma de obtener la clave principal de un NSManagedObject no debería ser un problema. He usado CoreData y la biblioteca C sqlite3 de bajo nivel juntas en el mismo código y pasar las claves primarias de CoreData a sqlite3 para obtener registros funciona bien.

! Si tiene la intención de usar este código en producción, tenga en cuenta los posibles cambios internos en la forma en que la clave principal de db se transforma en una representación URIR, podría frenar su código.

disfrutar

manitu
fuente
1
No se define ninguna relación entre ID de objeto y SQLite RID. Podría usarse para la clave temporal solo para una versión específica, pero el enfoque es incorrecto para la clave principal persistente porque puede romperse en otra versión de forma silenciosa.
eonil
¿Qué quiso decir exactamente con "roto en otra versión"? ¿Por qué deberían cambiar las claves primarias?
manitu
Los valores de PK no se cambiarán, pero el algoritmo que hace la representación de URL puede cambiarse, porque ningún algoritmo está definido oficialmente. Y en ese caso, no se garantiza que su código extraiga un valor PK válido. (si tiene alguna fuente que defina el algoritmo, hágamelo saber, luego le recomendaré que publique)
eonil
1
OKAY. a veces, cuando hackear parte es convincente. Mi voto en contra está actualmente bloqueado, por lo que si hace una edición, eliminaré el voto en contra.
eonil
2
En aras de la velocidad y la eficacia, sql es a veces el camino a seguir. Mi ejemplo, una consulta que contiene recuento (*), sumas, promedios y grupos. Es un DOLOR hacerlo en OO, ¡una sola línea para sql! Ese 'truco' funciona perfectamente y si Apple lo cambia, tendrán que hacer que la unión sql funcione de alguna manera, así que supongo que estaremos bien por un tiempo;). Vote ARRIBA incluso si en teoría no deberíamos hacer esto. Ocultar completamente la base de datos es, en mi opinión, un error más motivado por principios que por razones técnicas reales. Hacemos eso, obtenemos lotes por SQL. todo el tiempo en muchos otros sistemas, aunque hay un marco disponible.
Eric Giguere
0

Sin hackear NSManagedObjectID, puede realizar una verificación rápida de su atributo antes de administrar su recopilación de datos remota.

He creado un método de utilidad, compruébalo aquí

danielemm
fuente
0

Una extensión Swift para recuperar la clave principal

extension NSManagedObject {
    var primaryKey : String {
        guard objectID.uriRepresentation().lastPathComponent.count > 1 else { return "" }
        return objectID.uriRepresentation().lastPathComponent.substring(from: 1)
    }
}

Y para String

extension String
{
    func substring(from : Int) -> String {
        guard self.count > from else { return "" }
        return String(self[self.index(self.startIndex, offsetBy: from)...])
     }
}
Ryan Heitner
fuente
-3

Prefiero usar Time + el nombre de la clase como identificador único.

Bucle infinito
fuente
2
No es muy recomendable, ¿cuándo puede garantizar que no se cree más de un objeto al mismo tiempo?
fat32
No recomendado también. Este método no puede garantizar que la clave sea única.
Cody
@Fynh No publiqué el código y mi publicación puede estar incompleta, sin embargo, siempre estoy sincronizando el método de obtención de tiempo.
infiniteLoop