Można utworzyć drugą kolumnę w tabeli, która zawiera ciąg bez znaków międzynarodowych. Ponadto przed wykonaniem wyszukiwania w tej dodatkowej kolumnie wyszukiwania należy również usunąć znaki międzynarodowe z szukanego ciągu znaków (w ten sposób porównuje się dane nie-międzynarodowe z nie-międzynarodowymi).
To rutynowe używam do konwersji międzynarodowych znaków:
NSData *data = [string dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES];
string = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
Można również zastąpić znaki akcentowane z:
NSMutableString *mutableString = [string mutableCopy];
CFStringTransform((__bridge CFMutableStringRef)mutableString, NULL, kCFStringTransformStripCombiningMarks, NO);
Przy okazji, jeśli chcesz posortować wyniki możesz również sortować to dodatkowe pole wyszukiwania zamiast głównego pola, co pozwoli uniknąć problemów wynikających z niezdolności SQLite do sortowania znaków międzynarodowych.
Można alternatywnie utworzyć własną funkcję „akcentu” c (zdefiniować tę funkcję C poza @implementation
dla swojej klasie):
void unaccented(sqlite3_context *context, int argc, sqlite3_value **argv)
{
if (argc != 1 || sqlite3_value_type(argv[0]) != SQLITE_TEXT) {
sqlite3_result_null(context);
return;
}
@autoreleasepool {
NSMutableString *string = [NSMutableString stringWithUTF8String:(const char *)sqlite3_value_text(argv[0])];
CFStringTransform((__bridge CFMutableStringRef)string, NULL, kCFStringTransformStripCombiningMarks, NO);
sqlite3_result_text(context, [string UTF8String], -1, SQLITE_TRANSIENT);
}
}
Następnie można zdefiniować funkcję SQLite, które nazywają to C-funkcji (wywołanie tej metody po otwarciu bazy danych, która będzie obowiązywać do czasu zamknięcia tej bazy):
- (void)createUnaccentedFunction
{
if (sqlite3_create_function_v2(database, "unaccented", 1, SQLITE_ANY, NULL, &unaccented, NULL, NULL, NULL) != SQLITE_OK)
NSLog(@"%s: sqlite3_create_function_v2 error: %s", __FUNCTION__, sqlite3_errmsg(database));
}
zrobiwszy, że można teraz korzystać z tej nowej unaccented
funkcji w SQL, np:
if (sqlite3_prepare_v2(database, "select a from table where unaccented(column) like 'a'", -1, &statement, NULL) != SQLITE_OK)
NSLog(@"%s: insert 1: %s", __FUNCTION__, sqlite3_errmsg(database));
Tak, byłem przy użyciu tej metody zbyt, ale teraz Muszę zająć się bazą danych, której nie mogę zmienić. Ale jeśli możesz, a twoja db nie jest zbyt duża, jest to prosta droga. –
@ LeandroAlves Wiem, że już dawno temu minęło ten problem, ale ja (a) dołączam kolejną odmianę dla nieakcentujących ciągów; i (b) pokażę ci, jak w locie SQLite w locie nieakcentowane ciągi znaków. – Rob
@Rob Kod opcji 2 uruchamia i obsługuje dane poprawnie, ale zabiera CPU do 99% i Pamięć> 1000 MB. Aplikacja ulega awarii z 'EXC_BAD_ACCESS (kod = 2, adres = 0x0)' natychmiast po zakończeniu operacji. Czy jest coś, co można zrobić, aby kontrolować wykorzystanie pamięci za pomocą tego kodu? –