2009-08-19 3 views
0

(Примечание: Это расширение previous question.)Фильтрация словаря по значению ключа в суб словарях с UISearchBar

У меня возникли некоторые трудности, реализующий SearchBar для довольно сложной Tableview. TableView имеет несколько разделов, две строки текста и изображение. Все данные загружаются из plist, а затем помещаются в секции по начальной букве значения для клавиши «Name». NSLog возвращает следующий за мой основной словарь «sectionedDictionaryByFirstLetter»:

sectionedDictionaryByFirstLetter:{ 
B = (
    { 
    Name = "B...A Name Starting with B"; 
    Image = "ImageName1.png"; 
    Text = "Some Text"; 
    } 
    ); 
C = (
    { 
    Name = "C...A Name Starting with C"; 
    Image = "ImageName2.png"; 
    Text = "Some Text"; 
    } 
    ); 
N = (
    { 
    Name = "N1...A Name Starting with N"; 
    Image = "ImageName3.png"; 
    Text = "Some Text"; 
    }, 
    { 
    Name = "N2...A Name Starting with N"; 
    Image = "ImageName4.png"; 
    Text = "Some Text"; 
    }, 
    { 
    Name = "N3...A Name Starting with N"; 
    Image = "ImageName5.png"; 
    Text = "Some Text"; 
    } 
); 
} 

Я хочу, чтобы фильтровать вложенные словари от значения ключа «Name». Может ли кто-нибудь порекомендовать либо как это сделать, либо некоторые ресурсы для обучения? Я слежу за примером в «Начало разработки iPhone 3», но не смог перевести его в свою ситуацию. Таким образом, если пользователь введет «с N» в строке поиска, я хотел бы, чтобы новый словарь, чтобы выглядеть следующим образом:

filteredSectionedDictionaryByFirstLetter:{ 
N = (
    { 
    Name = "N1...A Name Starting with N"; 
    Image = "ImageName3.png"; 
    Text = "Some Text"; 
    }, 
    { 
    Name = "N2...A Name Starting with N"; 
    Image = "ImageName4.png"; 
    Text = "Some Text"; 
    }, 
    { 
    Name = "N3...A Name Starting with N"; 
    Image = "ImageName5.png"; 
    Text = "Some Text"; 
    } 
); 
} 

Просто чтобы прояснить, я мой SearchBar установлен в представлении, я просто с проблема делает его функциональным. В настоящее время я использую собственный метод, называемый - (void) handleSearchForTerm: (NSString *) searchTerm из примера в книге.

Спасибо за помощь!


Общая информация о составе.

sectionedDictionaryByFirstLetter 

Key Value 
B Array of Dictionaries with Names beginning with B 
     .... 
C Array of Dictionaries with Names beginning with C 
     ... 
N Array of Dictionaries with Names beginning with N 
    Item 1 Dictionary 1 
    Item 2 Dictionary 2 
    Item 3 Dictionary 3 

      Dictionary 3 
      { 
      Name = "N3...A Name Starting with N"; 
      Image = "ImageName5.png"; 
      Text = "Some Text"; 
      } 

Надеюсь, это поможет. Я все еще отчаянно ищу ответ на эту проблему.

По существу, есть первичный словарь, у которого есть ключи, это первые буквы элементов, которые он содержит. Внутри каждой первой буквы имеется массив словарей, которые имеют значение для своего «имени», который начинается с этой буквы.

+0

См. Мой ответ, но вы не хотите использовать для этого список dicts. Вы хотите создать подкласс NSObject, и синтаксис не будет таким ужасным. –

ответ

0

Хорошо, я, наконец, ответил на свой вопрос. Вот код ниже. Я в основном следовал примеру поиска массива в разделе «Начало разработки iPhone 3». Мне пришлось немного изменить его, чтобы он работал для моей проблемы. Вот мой код:

- (void)handleSearchForTerm:(NSString *)searchTerm 
{ 
NSMutableArray *sectionsToRemove = [[NSMutableArray alloc] init]; 
[self resetSearch]; 
for (NSString *key in self.keys) 
{ 
    NSMutableArray *array = [self.copyOfSectionedDictionaryByFirstLetter valueForKey:key]; 
    NSMutableArray *toRemove = [[NSMutableArray alloc] init]; 
    for (NSDictionary *name in array) 
    { 
     if ([[name objectForKey:@"Name"] rangeOfString:searchTerm options:NSCaseInsensitiveSearch].location == NSNotFound) 
      [toRemove addObject:name]; 
    } 

if ([array count] == [toRemove count]) 
    [sectionsToRemove addObject:key]; 
[array removeObjectsInArray:toRemove]; 
[toRemove release]; 
} 

[self.keys removeObjectsInArray:sectionsToRemove]; 
[sectionsToRemove release]; 
[self.tableView reloadData]; 
} 

Если вы хотите, чтобы увидеть полный образец кода, чтобы увидеть, как это работает, вы можете скачать с сайта here «Начиная с iPhone 3 Development». Это пример раздела.

0

Update

Похоже, у вас есть массивы в привязке Письма в массиве.

я бы, вероятно, использовать NSPredicate и фильтр на любой ключ, я был заинтересован.

NSString *searchString = @"Nancy"; 

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"(Name == %@)", Nancy]; 

NSArray *filteredArray = [[sectionedDictionaryByFirstLetter objectForKey:@"N"] filteredArrayUsingPredicate:predicate]; 

Существует руководство по построению предиката.

Есть и другие способы, но это первое, что приходит на ум.


Оригинал ответа

Вы можете использовать метод KVC:

valueForKeyPath: 

Чтобы получить то, что вы хотите. Вы должны прочитать на яблоневых документах КЦА:

http://developer.apple.com/documentation/Cocoa/Conceptual/KeyValueCoding/

Есть много способов «играть» с словарями/массивами, чтобы сделать то, что вы хотите. Различные методы будут иметь разные преимущества/преимущества.

+0

Спасибо! Я взгляну. – Jonah

+0

У вас есть более конкретные идеи? У меня есть чертовски время, прорывая весь этот материал. Благодаря! – Jonah

+0

Большое спасибо за помощь! Кажется, это на правильном пути. Тем не менее, я хочу искать в каждой начальной букве, а не только в «N», как в вашем примере. Я также хочу, чтобы начальные буквы оставались в словаре, только если они содержат элементы. Я отредактировал вопрос, чтобы добавить немного больше ясности. – Jonah

0

Другая идея, которую я получил, - создать массив всех значений для «имени». Что-то вроде этого:

arrayOfNames:(
"B...A Name Starting with B", 
"C...A Name Starting with C", 
"N1...A Name Starting with N", 
"N2...A Name Starting with N", 
"N3...A Name Starting with N" 
) 

Затем запустите фильтр на этом массиве. Наконец, используйте filterArrayOfNames, чтобы добавить элементы в новый словарь с соответствующими именами. Это похоже на концептуальный подход на правильном пути? Есть ли лучший маршрут?

1

Ваша структура данных запутывает вас.

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

Таким образом, вы бы иметь массив так:

[[NSArray alloc] initWithObjects: 
    [[NSDictionary alloc] initWithObjectsAndKeys: 
    @"a1", @"name", foo, @"bar", nil)],nil], 
    [[NSDictionary alloc] initWithObjectsAndKeys: 
    @"b21", @"name", foo, @"bar", nil)],nil]; 

Тогда это просто. Просто отфильтруйте отсортированный массив с помощью ввода в строке поиска. Вы даже можете сохранить ваши записи в базе данных CoreData, конец объявить функцию, которая делает что-то вроде этого, чтобы получить их:

if (!self.wordList) { 
    self.wordList = [self getWiordList] 
} else { 
    return self.wordList; 
} 

Кроме того, я хотел бы предложить вам создать подкласс NSObject и использовать массив из тех, вместо словарей, так что вам нужен доступ к точкам, а синтаксис хорош. Работа с dicts и списками в Obj C не так хороша, как в Python.

Подклассификация NSObject проста.

+0

Спасибо за ваш ответ. Причина, по которой я использую словарь, разбитый на подклассы, заключается в отображении секционированного представления таблицы. Прямо сейчас таблица прекрасно отображает все ячейки, отсортированные и под правильным разделом с заголовками для каждой буквы, а также индекс раздела. Я не уверен, как бы я воссоздал этот проект с данными, структурированными, как вы предлагаете. Однако я мог бы реструктурировать его, как вы рекомендуете для фильтрации, а затем изменить его обратно в текущий формат для отображения данных. Кроме того, я, возможно, забыл упомянуть, что данные хранятся в plist. – Jonah

Смежные вопросы