O problema é se o banco de dados tem uma comparação diacrítica insensível. A outra questão são os caracteres compostos, ï pode ser expresso como um caractere unicode ou dois formando um par substituto. Existem métodos para converter uma string em uma forma pré-composta ou decomposta:precomposedStringWith* e decomposedStringWith*.
Parece que o MySQL suporta duas formas de unicode ucs2 (que é uma forma mais antiga que foi substituída por utf16) que é de 16 bits por caractere e utf8 até 3 bytes por caractere. A má notícia é que nenhum dos formulários vai suportar caracteres do plano 1 que requerem 17 bits. (principalmente emojis). Parece que o MySQL 5.5.3 e superior também suportam utf8mb4, utf16 e utf32 suportam BMP e caracteres suplementares (leia emoji). Consulte Conjuntos de caracteres MySQL Unicode .
Aqui estão alguns códigos e resultados para demonstrar as diferentes representações de bytes unicode.
Unicode é um sistema de codificação de 21 bits.
UTF32 representa diretamente os pontos de código e demonstra claramente pares substitutos decompostos.
UTF8 e UTF16 requerem um ou mais bytes para representar um caractere unicode.
NSLog(@"character: %@", @"Å");
NSLog(@"decomposedStringWithCanonicalMapping UTF8: %@", [[@"Å" decomposedStringWithCanonicalMapping] dataUsingEncoding:NSUTF8StringEncoding]);
NSLog(@"decomposedStringWithCanonicalMapping UTF16: %@", [[@"Å" decomposedStringWithCanonicalMapping] dataUsingEncoding:NSUTF16BigEndianStringEncoding]);
NSLog(@"decomposedStringWithCanonicalMapping UTF32: %@", [[@"Å" decomposedStringWithCanonicalMapping] dataUsingEncoding:NSUTF32BigEndianStringEncoding]);
NSLog(@"precomposedStringWithCanonicalMapping UTF8: %@", [[@"Å" precomposedStringWithCanonicalMapping] dataUsingEncoding:NSUTF8StringEncoding]);
NSLog(@"precomposedStringWithCanonicalMapping UTF16: %@", [[@"Å" precomposedStringWithCanonicalMapping] dataUsingEncoding:NSUTF16BigEndianStringEncoding]);
NSLog(@"precomposedStringWithCanonicalMapping UTF32: %@", [[@"Å" precomposedStringWithCanonicalMapping] dataUsingEncoding:NSUTF32BigEndianStringEncoding]);
NSLog(@"character: %@", @"😱");
NSLog(@"dataUsingEncoding UTF8: %@", [@"😱" dataUsingEncoding:NSUTF8StringEncoding]);
NSLog(@"dataUsingEncoding UTF16: %@", [@"😱" dataUsingEncoding:NSUTF16BigEndianStringEncoding]);
NSLog(@"dataUsingEncoding UTF32: %@", [@"😱" dataUsingEncoding:NSUTF32BigEndianStringEncoding]);
// Para alguns pares substitutos não existe outra forma
NSString *aReverse = [[NSString alloc] initWithBytes:"\xD8\x3C\xDD\x70\x00" length:4 encoding:NSUTF16BigEndianStringEncoding];
NSLog(@"character: %@", aReverse);
NSLog(@"dataUsingEncoding UTF8: %@", [aReverse dataUsingEncoding:NSUTF8StringEncoding]);
NSLog(@"dataUsingEncoding UTF16: %@", [aReverse dataUsingEncoding:NSUTF16BigEndianStringEncoding]);
NSLog(@"dataUsingEncoding UTF32: %@", [aReverse dataUsingEncoding:NSUTF32BigEndianStringEncoding]);
Saída NSLog:
character: Å
decomposedStringWithCanonicalMapping UTF8: <41cc8a>
decomposedStringWithCanonicalMapping UTF16: <0041030a>
decomposedStringWithCanonicalMapping UTF32: <00000041 0000030a>
precomposedStringWithCanonicalMapping UTF8: <c385>
precomposedStringWithCanonicalMapping UTF16: <00c5>
precomposedStringWithCanonicalMapping UTF32: <000000c5>
character: 😱
dataUsingEncoding UTF8: <f09f98b1>
dataUsingEncoding UTF16: <d83dde31>
dataUsingEncoding UTF32: <0001f631>
character: 🅰
dataUsingEncoding UTF8: <f09f85b0>
dataUsingEncoding UTF16: <d83cdd70>
dataUsingEncoding UTF32: <0001f170>