Tengo un UITextView y necesito para detectar si un usuario escribe un carácter de emoji.

Yo creo que solo revisando el valor unicode de la más reciente personaje sería suficiente, pero con los nuevos emoji 2s, algunos caracteres se dispersa por todo el índice unicode (es decir, de Apple, el nuevo diseño de los derechos de autor y registro de logos).

Tal vez algo que ver con la comprobación de la lengua del personaje con NSLocale o LocalizedString valores?

¿Alguien sabe una buena solución?

Gracias!

Por curiosidad, ¿por qué quieres para detectar esto?
Estoy haciendo un editor de texto que añade efectos de texto a través de HTML/CSS, pero el texto se introduce a través de un UITextField…. Emojis no mostrar correctamente con mi CSS efectos por lo que necesito para no permitir a los usuarios el uso de ellos.
De regreso después de 3 años – es posible agregar a un UILabel y ver si la fuente asignada es AppleColorEmoji? Usted también podría instantánea UILabel w/ el carácter y el promedio de los píxeles en uno y ver si es negro, si no es un emoji (con la excepción de negro sólido emojis)

OriginalEl autor Albert Renshaw | 2013-01-15

6 Comentarios

  1. 17

    Lo largo de los años estos emoji-detección de soluciones de mantener rompe como Apple añade nuevos emojis w/nuevos métodos (como la piel de tono emojis construido por la pre-maldecir a un personaje con un carácter adicional), etc.

    Que finalmente se rompió y sólo escribió el siguiente método que funciona para todos los emojis y debe trabajar para que en el futuro todos los emojis.

    La solución crea un UILabel con el personaje y con un fondo negro. CG, a continuación, toma una instantánea de la etiqueta y puedo escanear todos los píxeles de la imagen para no sólido de píxeles negros. La razón por la que añadir el fondo negro es para evitar problemas de falsos colorear debido a Subpixel De Representación

    La solución se ejecuta MUY rápido en mi dispositivo, puedo comprobar cientos de personajes de un segundo, pero debe tenerse en cuenta que este es un CoreGraphics solución y no deben ser utilizadas como usted puede con un texto normal método. Los gráficos del procesamiento de los datos es pesado para la comprobación de miles de personajes a la vez podría resultar en un notable retraso.

    -(BOOL)isEmoji:(NSString *)character {
    UILabel *characterRender = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 1, 1)];
    characterRender.text = character;
    characterRender.backgroundColor = [UIColor blackColor];//needed to remove subpixel rendering colors
    [characterRender sizeToFit];
    CGRect rect = [characterRender bounds];
    UIGraphicsBeginImageContextWithOptions(rect.size,YES,0.0f);
    CGContextRef contextSnap = UIGraphicsGetCurrentContext();
    [characterRender.layer renderInContext:contextSnap];
    UIImage *capturedImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    CGImageRef imageRef = [capturedImage CGImage];
    NSUInteger width = CGImageGetWidth(imageRef);
    NSUInteger height = CGImageGetHeight(imageRef);
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    unsigned char *rawData = (unsigned char*) calloc(height * width * 4, sizeof(unsigned char));
    NSUInteger bytesPerPixel = 4;
    NSUInteger bytesPerRow = bytesPerPixel * width;
    NSUInteger bitsPerComponent = 8;
    CGContextRef context = CGBitmapContextCreate(rawData, width, height,
    bitsPerComponent, bytesPerRow, colorSpace,
    kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);
    CGColorSpaceRelease(colorSpace);
    CGContextDrawImage(context, CGRectMake(0, 0, width, height), imageRef);
    CGContextRelease(context);
    BOOL colorPixelFound = NO;
    int x = 0;
    int y = 0;
    while (y < height && !colorPixelFound) {
    while (x < width && !colorPixelFound) {
    NSUInteger byteIndex = (bytesPerRow * y) + x * bytesPerPixel;
    CGFloat red = (CGFloat)rawData[byteIndex];
    CGFloat green = (CGFloat)rawData[byteIndex+1];
    CGFloat blue = (CGFloat)rawData[byteIndex+2];
    CGFloat h, s, b, a;
    UIColor *c = [UIColor colorWithRed:red green:green blue:blue alpha:1.0f];
    [c getHue:&h saturation:&s brightness:&b alpha:&a];
    b /= 255.0f;
    if (b > 0) {
    colorPixelFound = YES;
    }
    x++;
    }
    x=0;
    y++;
    }
    return colorPixelFound;
    }
    Nunca he visto una solución en la que la creación de una rígida matriz de valores era una buena idea. Esta sugerencia es excepcionalmente malo en ser rife para el error y no en el futuro. Una mejor solución sería el uso combinado de la consulta de la textInputMode de la UITextView en cuestión y ver si el primaryLanguage es «emoji»
    Sí, a menos que copiar y pegar un emoji en, o utilizar un teclado personalizado (iOS8 Extensión de la Aplicación), que tiene carácter de emoji pero ha primaryLanguage inglés.
    Podría actualizar allEmojis matriz en iOS8.3?
    Editado mi viejo soluciones y escribió un CG solución, caso omiso a comentarios anteriores
    Solución interesante, pero me gustaría publicarlo de una forma completamente nueva respuesta y la reversión de esta respuesta a su estado anterior.

    OriginalEl autor Albert Renshaw

  2. 3

    Otra solución: https://github.com/woxtu/NSString-RemoveEmoji

    Luego, después de la importación de esta extensión, se puede utilizar como esto:

    - (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text
    {
    //Detect if an Emoji is in the string "text"
    if(text.isIncludingEmoji) {
    //Show an UIAlertView, or whatever you want here
    return NO;
    }
    return YES;
    }

    Espero que ayude 😉

    Por favor, tenga en cuenta que iOS 9.1 añadido más emojis que anteriormente mencionado método no reconoce (especialmente estos:🤐🤑🤒🤓🤔🤕🤖🤗🤘🦀🦁🦂🦃🦄🧀). REVISIÓN: reemplazar return (0x1d000 <= codepoint && codepoint <= 0x1f77f); en isEmoji método con return (0x1d000 <= codepoint && codepoint <= 0x1f77f) || (0x1F900 <= codepoint && codepoint <=0x1f9ff);

    OriginalEl autor Lapinou

  3. 3

    Primero que vamos a abordar su «55357 método» – y por qué funciona para muchos caracteres emoji.

    De Cacao, un NSString es una colección de unichars, y unichar es sólo un typealias para unsigned short que es el mismo que UInt16. Puesto que el valor máximo de UInt16 es 0xffff, esto descarta bastantes emoji de ser capaz de encajar en una unichar, ya que sólo dos de los seis principales Unicode bloques utilizados para emoji caen dentro de esta gama:

    Estos bloques contienen 113 emoji, y un adicional de 66 emoji que puede ser representado como una sola unichar se pueden encontrar distribuidos en torno a diversos otros bloques. Sin embargo, estos 179 caracteres sólo representan una fracción de los 1126 emoji de la base de caracteres, el resto de lo que debe ser representado por más de una unichar.

    Vamos a analizar el código:

    unichar unicodevalue = [text characterAtIndex:0];

    Lo que sucede es que simplemente eres de tomar el primer unichar de la cadena, y aunque esto funciona para el mencionado anteriormente 179 los personajes, que se rompe cuando se encuentre con un UTF-32 caracteres, ya que NSString convierte todo en la codificación UTF-16. La conversión obras de la sustitución de la UTF-32 con los pares suplentes, lo que significa que el NSString ahora contiene dos unichars.

    Y ahora estamos consiguiendo a por qué el número 55357, o 0xd83d, aparece para muchos emoji: cuando sólo mira el primer UTF-16 valor de un UTF-32 caracteres de obtener el alta sustituto, de cada uno de los cuales tienen una envergadura de 1024 baja sustitutos. La gama de la alta sustituto 0xd83d es U+1F400–U+1F7FF, que se inicia en medio de la mayor emoji bloque, Miscelánea de Símbolos y Pictogramas (U+1F300–U+1F5FF), y sigue todo el camino hasta Formas Geométricas Extendida (U+1F780–U+1F7FF) – que contiene un total de 563 emoji, y 333 no caracteres emoji dentro de este rango.

    Así, un impresionante 50% de emoji base de los caracteres tienen el alto sustituto 0xd83d, pero estos métodos de deducción todavía dejan 384 caracteres emoji no controlada, junto con dar falsos positivos para al menos como muchos.


    Así que, ¿cómo se puede detectar si un carácter es un emoji o no?

    Recientemente he respondido a una algo relacionado con la pregunta con una rápida aplicación, y si quieres, puedes mirar cómo los emoji son detectados en este marco, que he creado para el propósito de reemplazar el estándar de emoji con imágenes personalizadas.

    De todos modos, lo que puedes hacer es extraer el UTF-32 código de punto de los personajes, que vamos a hacer de acuerdo a la especificación:

    - (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text {
    //Get the UTF-16 representation of the text.
    unsigned long length = text.length;
    unichar buffer[length];
    [text getCharacters:buffer];
    //Initialize array to hold our UTF-32 values.
    NSMutableArray *array = [[NSMutableArray alloc] init];
    //Temporary stores for the UTF-32 and UTF-16 values.
    UTF32Char utf32 = 0;
    UTF16Char h16 = 0, l16 = 0;
    for (int i = 0; i < length; i++) {
    unichar surrogate = buffer[i];
    //High surrogate.
    if (0xd800 <= surrogate && surrogate <= 0xd83f) {
    h16 = surrogate;
    continue;
    }
    //Low surrogate.
    else if (0xdc00 <= surrogate && surrogate <= 0xdfff) {
    l16 = surrogate;
    //Convert surrogate pair to UTF-32 encoding.
    utf32 = ((h16 - 0xd800) << 10) + (l16 - 0xdc00) + 0x10000;
    }
    //Normal UTF-16.
    else {
    utf32 = surrogate;
    }
    //Add UTF-32 value to array.
    [array addObject:[NSNumber numberWithUnsignedInteger:utf32]];
    }
    NSLog(@"%@ contains values:", text);
    for (int i = 0; i < array.count; i++) {
    UTF32Char character = (UTF32Char)[[array objectAtIndex:i] unsignedIntegerValue];
    NSLog(@"\t- U+%x", character);
    }
    return YES;
    }

    Escribir «😎» en el UITextView escribe esto en la consola:

    😎 contains values:
    - U+1f60e

    Con esa lógica, basta con comparar el valor de character a la fuente de datos de emoji puntos de código, y usted sabrá exactamente si el personaje es un emoji o no.


    P. S.

    Hay un par de «invisible» personajes, a saber, Selectores De Variación y de ancho cero carpinteros, que también debe ser manejado, por lo que recomendamos el estudio de aquellos a aprender cómo se comportan.

    Gracias por la explicación profunda! Me preguntaba cómo funcionaba todo. Los pares suplentes son interesantes! Debe también ser observado que muchos caracteres emoji se han añadido a la norma unicode desde mi post original en el 2013, entonces lo que hizo la cuenta para casi todos los emojis creo que excepto, tal vez, un par de banderas. Voy a marcar esto como la nueva aceptado respuesta, gracias de nuevo!
    No hay problemas! Y por supuesto, es probablemente trabajaba para la mayoría de los emoji, pero también tomar en cuenta que se hubiera despedido de unos pocos cientos de no-caracteres emoji. Sí, banderas constan de dos combinados regional indicador de símbolos, por lo que todas las banderas caería fuera del rango de la 55357 alta sustituto.

    OriginalEl autor xoudini

  4. 2

    si no desea que su teclado para mostrar emoji puede utilizar
    YOURTEXTFIELD/YOURTEXTVIEW.keyboardType = .ASCIICapable

    Esto mostrará un teclado sin emoji

    Sí, pero el usuario puede pegar emojis en

    OriginalEl autor A_Curious_developer

  5. -3

    Bien puede detectar si sólo tiene los caracteres ascii que utiliza este:

    [myString canBeConvertedToEncoding:NSASCIIStringEncoding];

    Va a decir que no si se produce un error (o ha emoji). Entonces usted puede hacer un if else instrucción que no les permiten haga clic en intro o algo.

    Yo no haría eso. Básicamente, cualquier no-inglés las necesidades del usuario de signos diacríticos, y estos no son ASCII. Que podría causar una gran cantidad de falsos positivos.
    entonces, ¿qué tipo de codificación que contiene los signos diacríticos. En el código, puede cambiar NSASCIIStringEncoding a alguna otra codificación que usted sabe.
    sólo Unicode tiene emojis, pero al mismo tiempo, sólo Unicode tiene todos los caracteres de todos los idiomas. No hay un único tipo de codificación que tiene todos los caracteres excepto emojis. Es por eso que no me gusta de esta solución.
    Tal vez si haces algo como una y la declaración utilizando &&y tal vez tener una o declaración de usint || podría funcionar! (ex: ([myString canBeConvertedToEncoding:NSASCIIStringEncoding] || [myString canBeConvertedToEncoding:NSNSUTF8StringEncoding]) )
    Todos los caracteres Unicode (incluyendo Emoji) se puede convertir a UTF-8, por lo que esto no ayuda.

    OriginalEl autor Nate Lee

  6. -4

    Caracteres Emoji longitud es 2 y así comprobar si la longitud de la cadena es de 2 en el método que se shouldChangeTextInRange: que se llama después de cada tecla en el teclado de golpe

    - (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text
    {
    //Detect if an Emoji is in the string "text"
    if([text length]==2) {
    //Show an UIAlertView, or whatever you want here
    return YES;
    }
    else
    {
    return NO;
    }
    } 
    No, no todos los caracteres emoji de longitud 2, y también hay MUCHOS caracteres unicode de longitud 2 que va a dar falsos positivos por este.

    OriginalEl autor muhammad kashif Jawad

Dejar respuesta

Please enter your comment!
Please enter your name here