Objective-C выборочно заполнять таблицу из plist; если ключ равен

plist1 — это массив из 40 словарей по 4 строки в каждом. plist2 тоже массив, но из 120 словарей по 2 строки в каждом.

Если я перечислю все команды хоккейной лиги в таблице (заполненной из определенного ключа в plist1), скажем, я выберу пятую из них. Это толкает новую таблицу. 120 словарей в plist2 состоят из двух строк: одна соответствует году истории лиги по порядку, а другая — тому, кто выиграл чемпионат в этом году. Я хочу, чтобы во второй таблице отображались только те годы, для которых вторым ключом словаря является то же имя команды, которое было только что выбрано в первой таблице, plist1. Итак, когда я выбираю команду «5» из первой таблицы, я ожидаю увидеть во второй таблице только те годы, в которых команда «5» выиграла. Идея состоит в том, что все годы будут присутствовать в plist2, но неактуальные будут заблокированы в реальной таблице на ходу.

Как я могу сказать, что «если пользователь выбрал команду X, то показывать годы только для команды X, а не все годы».

Благодарю вас!


person naweinberger    schedule 24.11.2011    source источник


Ответы (1)


На самом деле вы можете довольно хорошо выполнять такую ​​фильтрацию, используя NSPredicate:

NSDictionary *testA = [NSDictionary dictionaryWithObjectsAndKeys:@"valA", @"key1", @"1", @"key2", nil];
NSDictionary *testB = [NSDictionary dictionaryWithObjectsAndKeys:@"valB", @"key1", @"2", @"key2", nil];
NSDictionary *testC = [NSDictionary dictionaryWithObjectsAndKeys:@"valC", @"key1", @"1", @"key2", nil];
NSDictionary *testD = [NSDictionary dictionaryWithObjectsAndKeys:@"valD", @"key1", @"3", @"key2", nil];

NSArray *testArr = [NSArray arrayWithObjects:testA, testB, testC, testD, nil];

NSPredicate *pred = [NSPredicate predicateWithFormat:@"key2 == %@", @"1"];
NSArray *testFilter = [testArr filteredArrayUsingPredicate:pred];

NSLog(@"%@", testFilter);

Эта установка создает 4 словаря и их массив. Выражение фильтра теперь ищет все содержащиеся объекты, где key2 равно 1, что должно быть testA и testC. И вуаля есть вывод:

2011-11-24 18:57:07.822 testapp[9977:f803] (
        {
        key1 = valA;
        key2 = 1;
    },
        {
        key1 = valC;
        key2 = 1;
    }
)

Таким образом, вы можете создать предикат для фильтрации по имени вашей команды и создать отфильтрованную версию вашего массива. Как правило, это работает со всеми типами объектов, которые поддерживают кодирование ключ-значение (что делает NSDictionary, дополнительная информация об этом: http://developer.apple.com/library/ios/#documentation/Cocoa/Conceptual/KeyValueCoding/Articles/BasicPrinciples.html#//apple_ref/doc/uid/20002170)

person Dennis Bliefernicht    schedule 24.11.2011
comment
Спасибо за ответ! Можно ли как-то использовать существующий массив в списках вместо создания новых словарей в коде? Может быть, я мог бы позвонить им...? Я сделал это с первой таблицей, выполнив следующее: - (void)viewDidLoad { [super viewDidLoad]; NSString *path = [[NSBundle mainBundle] pathForResource:@"ChronoWSH" ofType:@"plist"]; NSArray* tmpArray = [[NSArray alloc] initWithContentsOfFile:path]; self.chronologicallyArray = tmpArray; [tmpArray release]; затем cell.textLabel.text = [[self.chronologicallyArray objectAtIndex:indexPath.row] objectForKey:YEAR_KEY]; - person naweinberger; 24.11.2011
comment
Конечно, словари нужны были только для создания примеров. В своем коде вы должны начать со строки NSPredicate и использовать filteredArrayUsingPredicate непосредственно в своем собственном массиве plist. - person Dennis Bliefernicht; 24.11.2011
comment
Это имеет смысл, спасибо. Последнее, что я не совсем понимаю, это @"key2==%@", @"1"]; Что я должен туда добавить, чтобы гарантировать, что программа загрузит правильную строку, так как строка будет различаться в зависимости от команды. Это должна быть переменная. Должен ли я настроить его, сказав, что key2 — это название команды, и что key2 должен равняться строке имени? Я довольно неопытен, спасибо за ваше терпение. - person naweinberger; 24.11.2011
comment
key2 — это ключ, используемый в словаре для фильтрации. Я предполагаю, что ваш словарь настроен таким образом, что есть ключ с именем teamname и ключевым годом с соответствующими значениями. Тогда вы бы поставили teamname вместо key2 и вы можете использовать переменную для фильтруемого имени команды вместо константы @"1" в моем примере. - person Dennis Bliefernicht; 24.11.2011
comment
Да, извините, я просто не знаю, как определить эту переменную. Должен ли я создать NSString для didSelectRowAtIndexPath, а затем подключить этот NSString в качестве моей переменной? - person naweinberger; 24.11.2011
comment
Если я правильно понимаю концепцию вашего приложения, вы должны передать выбранное имя команды из первого контроллера представления (список команд) во второе представление (отфильтрованный список по имени команды). Затем контроллер представления отфильтрованного списка в своем методе viewDidLoad создаст отфильтрованную копию массива и сохранит ее локально на основе этой переменной, так же, как вы делаете это в своей первой таблице в комментарии выше. Контроллер отфильтрованного представления теперь имеет свой собственный отфильтрованный список и может отображать его так, как если бы другого списка не было. - person Dennis Bliefernicht; 24.11.2011
comment
Я думаю, вы все правильно поняли, но не могли бы вы привести пример фактической передачи имени от одного контроллера представления к другому? Просто на самом деле создать переменную для выбранной команды, а затем включить ее в новую таблицу — это выше моего понимания. Извиняюсь! - person naweinberger; 24.11.2011
comment
Нет проблем, я описал шаги в другом потоке для передачи объекта NSDate между контроллерами представления. Может быть, этого достаточно: viewcontroller">stackoverflow.com/questions/8258735/ - person Dennis Bliefernicht; 24.11.2011
comment
Боюсь, я все еще немного запутался. В моем первом TableViewController у меня есть массив команд (алфавитный массив), определенный в .h и синтезированный в .m. У меня также есть массив с именем selectedTeam, который имеет @property и синтезирован. DetailViewController *detailViewController = [[DetailViewController alloc] initWithNibName:@"DetailViewController" bundle:nil]; detailViewController.alphabeticallyArray = selectedTeam; - person naweinberger; 25.11.2011
comment
Я только что немного изменил его, если вы не читали комментарий выше, не обращайте на него внимания: AlphabeticallyTableViewController *alphabeticallyTVC = [AlphabeticallyTableViewController alloc]; alphabeticallyTVC.alphabeticallyArray = selectedTeam; DetailViewController — это то, что я называю вторым контроллером таблицы. - person naweinberger; 25.11.2011
comment
Вы всегда можете загрузить свой массив во втором представлении. но вам нужно имя команды как свойство NSString. Предположим, вы объявили и синтезировали свойства teamName и dataArray в подробном представлении. В вашем viewDidLoad примерно так: `(void)viewDidLoad { [super viewDidLoad]; NSString path = [[NSBundle mainBundle] pathForResource:@secondFilePlistofType:@plist]; NSArray tmpArray = [[NSArray alloc] initWithContentsOfFile:path]; self.dataArray = [tmpArray filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@teamname == %@, self.teamName]]; [выпуск tmpArray];`` - person Dennis Bliefernicht; 25.11.2011
comment
Спасибо большое! Похоже, это именно то, что мне нужно! Я ценю вашу помощь! - person naweinberger; 26.11.2011