您可以在表中创建第二列,其中包含不带国际字符的字符串。此外,在对该辅助搜索列进行搜索之前,您还应该从正在搜索的字符串中删除国际字符(这样您就可以比较非国际与非国际)。
这是我用来转换国际字符的例程:
NSData *data = [string dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES];
string = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
您还可以将重音字符替换为:
NSMutableString *mutableString = [string mutableCopy];
CFStringTransform((__bridge CFMutableStringRef)mutableString, NULL, kCFStringTransformStripCombiningMarks, NO);
顺便说一句,如果您需要对结果进行排序,您也可以在这个辅助搜索字段而不是主字段上进行排序,这样也可以避免因 SQLite 无法对国际字符进行排序而引起的问题。
您也可以创建自己的“无重音”C 函数(在 @implementation 之外为您的班级定义此 C 函数):
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);
}
}
然后你可以定义一个 SQLite 函数来调用这个 C 函数(在你打开数据库后调用这个方法,直到你关闭那个数据库才有效):
- (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));
}
完成后,您现在可以在 SQL 中使用这个新的 unaccented 函数,例如:
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));