...

вторник, 23 июля 2013 г.

Динамический поиск строки в iOS


Недавно появилась задача — встроить в приложение динамический поиск информации, то есть выдача должна генерироваться параллельно вводу пользователем символов. Вся информация хранится в SQLite базе данных. Все бы ничего, но в каждом слове выдачи искомые символы должны подсвечиваться.

Было принято волевое решение не использовать внешние библиотеки, а попробовать обойтись своими силами.



Начнем с внешней формы.



В качестве поисковой строки используется UISearchBar . Результаты выводятся в обычный UITableView (в данном случае, с ячейками, кроме текста включающими в себя и картинку).

Обработчиком для события изменения текста в строке является:



- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText
{
_data = [SBHotspotData findHotspot:searchText];
[self.searchResultsTableView reloadData];
}




где _data — NSArray, хранящий результаты выдачи.

На этом этапе возникла проблема — во всех названиях объектов, по которым проводится поиск, есть как заглавные буквы, так и строчные, которые SQLite воспринимает по-разному, а функции lower() и upper(), в отличии от SQL, не поддерживаются. Путем наименьшего сопротивления решили добавить в базу данных отдельный столбец, хранящий в себе все те же заголовки, но уже в нижнем регистре, тем более, что в данном случае увеличение объема базы было практически незаметно. Метод поиска (для работы с БД используется библиотека FMDatabase):



+ (NSArray *) findHotspot: (NSString *)partOfTitle
{
SBHotspotData *item;
NSMutableArray *result = [NSMutableArray array];

NSString *path = [self getDatabasePath];
FMDatabase *database;
database = [FMDatabase databaseWithPath:path];
[database open];

NSString *query = [NSString stringWithFormat:@"select * from hotspots where TitleLow like '%%%@%%'", [partOfTitle lowercaseString]];
FMResultSet *results = [database executeQuery:query];

while([results next]) {
item = [[SBHotspotData alloc ]init];
item.hotspotIdentity = [results stringForColumn:@"Identity"];
item.hotspotTitle = [results stringForColumn:@"Title"];
item.hotspotDescription = [results stringForColumn:@"Description"];
[result addObject:item];
}

[database close];

return [result sortedArrayUsingSelector:@selector(compare:)];
}

- (NSComparisonResult)compare:(SBHotspotData *)otherObject {
return [self.hotspotTitle compare:otherObject.hotspotTitle];
}




При формировании запроса используется %%%@%%, где знаками процента обозначается, что перед и после строки может идти любое количество символов. Метод возвращает массив объектов из базы данных, отсортированный по алфавиту.

Самая интересная часть задания — подсветка введенных символов. Реализуется она следующим образом:

NSMutableAttributedString *attributedString =
[[NSMutableAttributedString alloc] initWithString:item.hotspotTitle];

NSRange range = [item.hotspotTitle rangeOfString:_searchHotspotBar.text];
[attributedString addAttribute:NSBackgroundColorAttributeName
value:[UIColor colorWithRed:216/255.0f green:87/255.0f blue:23/255.0f alpha:1.0f]
range:range];

cell.cellLabel.attributedText = attributedString;




Для подсветки определенных символов используется NSMutableAttributedString и его метод addAttribute:value:range:.

Ну и результат работы программы:



Задача получилась достаточно тривиальной, но, надеюсь, полученный опыт пригодится кому-либо из хабровчан.


This entry passed through the Full-Text RSS service — if this is your content and you're reading it on someone else's site, please read the FAQ at fivefilters.org/content-only/faq.php#publishers. Five Filters recommends: 'You Say What You Like, Because They Like What You Say' - http://www.medialens.org/index.php/alerts/alert-archive/alerts-2013/731-you-say-what-you-like-because-they-like-what-you-say.html


Комментариев нет:

Отправить комментарий