¿Cómo manejar caracteres unicode no estándar en CoreData?

Una cosa que leí en la web es esta

¡Rameeee! 👯👯

Entonces usa caracteres no estándar.

Intenté save eso en conetworkingata

NSManagedObjectContext * parentMoc = [self managedObjectContextMainContext]; //Main parent is not nsmainqueueconcurency type. Hence, this is save [parentMoc performBlockAndWait:^{ if (![parentMoc save:&error]) { CLog(@"Error in Saving %@", error);// handle error } }]; NSAssert(error==nil, @"Error must be nill"); 

Tengo este error:

 (lldb) po error domain: @"NSCocoaErrorDomain" - code: 1671 

Hmm … ¿qué debo hacer?

El código de error 1671 no está documentado. Sin embargo, los códigos de error 1660, 1670 y 1680 tratan con errores de validation de cadenas. Entonces veamos qué podemos encontrar …

Las cadenas válidas funcionan igual independientemente de si tienen Emoji o lo que sea. Siempre que la cadena contenga solo caracteres válidos, no se necesita un tratamiento especial. La cadena que provocó esta pregunta, tal como se publicó , se ajusta a esta descripción. Este código funciona y los cambios se guardan sin errores:

 NSString *testNSString = @"Rameeee! 👯👯"; [newManagedObject setValue:testNSString forKey:@"name"]; 

Un viaje networkingondo completo funciona exactamente como se esperaba, incluso se muestra correctamente en una UILabel en una celda de vista de text.

introduzca la descripción de la imagen aquí

Como resultado, está claro que la pregunta original está omitiendo detalles cruciales en alguna parte, porque la respuesta correcta es que no haces nada especial para manejar esos personajes, simplemente funcionan.

La cadena de muestra de @DevFly proporciona una pista:

 "\U05d4\U05d4\U05d9\U05ea\U05e8\U05d2\U05e9\U05d5\U05ea \U05db\U05dc \U05db\U05da \U05d2\U05d3\U05d5\U05dc\U05d4 \Ud83d" 

En realidad, no se puede build una cadena literal con estos contenidos sin una dificultad significativa. El comstackdor se queja de que el último carácter, \Ud83d es un "carácter universal no válido", y la compilation falla. Echando un vistazo a la tabla de códigos relevante de unicode.org confirma esto: \Ud83d está en el "área sustituta alta" y la tabla señala que

Los puntos de código sustitutos aislados no tienen interpretación; por consiguiente, no se proporcionan diagtwigs de códigos de caracteres ni lists de nombres para este range.

Lo que todo esto significa es que \Ud83d no es un carácter Unicode válido. No representa ningún carácter y no se puede convertir a codificaciones como UTF-8.

Si deja caer el carácter inválido desde el final, entonces, al igual que el anterior, funciona normalmente sin un manejo especial:

 char *testString = "\u05d4\u05d4\u05d9\u05ea\u05e8\u05d2\u05e9\u05d5\u05ea \u05db\u05dc \u05db\u05da \u05d2\u05d3\u05d5\u05dc\u05d4"; NSString *testNSString = [NSString stringWithUTF8String:testString]; [newManagedObject setValue:testNSString forKey:@"name"]; 

Eso ahorra sin errores, y de nuevo realiza un viaje networkingondo completo y se muestra correctamente en un UILabel :

introduzca la descripción de la imagen aquí

Lo que todo esto significa es:

  • Este error significa que de alguna manera está construyendo una cadena que contiene bytes no válidos que no representan ningún carácter.
  • Esto no se debe a que los caracteres son Unicode, porque un Unicode válido está bien. Pero no todos los valores hexadecimales numéricos representan un carácter Unicode, por lo que es posible tener un valor corrupto que no se puede usar en una cadena.
  • Dado que ni @JimThio ni @DevFly ni @SharenEayrs parecen querer explicar cómo crearon sus problemáticos vectores de bytes (realmente no puedo llamarlos "cadenas"), es imposible decir qué causó originalmente el problema. Pero esos datos están corruptos, período , y solo se parece a un problema de datos básicos porque ahí es donde está utilizando los datos.
  • Una causa probable es que en algún momento estas cadenas fueron alteradas en el código sin considerar que no todos los caracteres usan el mismo número de bytes. Hacer cosas como cambiar cadenas basadas en índices de caracteres es probable que cause problemas. Podría ser útil revisar la guía "Caracteres y charts de Cluster de Apple " y quizás el artículo de NSHipster sobre codificaciones de types .
  • La sugerencia de NSData de usar NSData podría funcionar, pero probablemente no, a less que NSData a un código extraño donde evites usar esos bytes en una cadena (por ejemplo, no uses dataUsingEncoding: para convertir a NSData ). Incluso si lo hace, todavía tendrías datos corruptos , y te mordería tarde o temprano.

Actualización relacionada con una cadena dada en un comentario:

 NSString *testNSString = @"👦🏻 👧🏻 👨🏻 👩🏻 👮🏻 👰🏻 👱🏻 👲🏻 👳🏻 👴🏻 👵🏻 👶🏻 👷🏻 👸🏻 💂🏻 👼🏻 🎅🏻 🙇🏻 💁🏻 🙅🏻 🙆🏻 🙋🏻 🙎🏻 🙍🏻 💆🏻 💇🏻 💅🏻 👂🏻 👃🏻 👋🏻 👍🏻 👎🏻 ☝🏻 👆🏻 👇🏻 👈🏻 👉🏻 👌🏻 ✌🏻 👊🏻 ✊🏻 ✋🏻 💪🏻 👐🏻 🙌🏻 👏🏻 🙏🏻"; [newManagedObject setValue:testNSString forKey:@"name"]; 

De nuevo, esto se guarda sin errores, y regresa a la interfaz de usuario más tarde exactamente como se muestra arriba, incluso después de matar la aplicación y volver a iniciarla. Si esto de algún modo se está rompiendo, Core Data no lo está corrompiendo.

NSCocoaErrorDomain errores NSCocoaErrorDomain con códigos entre 1024 y 2048 son errores de validation. Una de las reglas de validation que se ha establecido en el model no pasa.