Когда я пытаюсь добавить NSDictionary в NSMutableArray, я не могу заменить последний добавленный объект

#objective-c #xcode #nsmutablearray #nsmutabledictionary

#objective-c #xcode #nsmutablearray #nsmutabledictionary

Вопрос:

Мне нужно добавить NSDictionary в NSMutableArray .

Сначала я создал NSMutableDictionary со значением ключа из другой структуры, подобной этой:

 for (NSString *key in selectedFiltersByUser) {
    [filters_data setObject:key forKey:@"key"];
    [filters_data setObject:selectedFiltersByUser[key] forKey:@"value"];

    // Added filter selected id's into Array for all query_params
    [query_params addObject:filters_data];
}
  

selectedFiltersByUser — это словарь, подобный этому:

 {
category_id = "XXX";
sort = "last_updated_asc";
status = "rejected_by_seller";
}
  

и для каждого ключа: значения в этом словаре я создаю новый NSMutableDictionary, подобный этому:

 {
  key: category_id,
  value: XXX
}
  

И этот новый объект, NSMutableDictionary добавленный в NSMutableArray , выглядит следующим образом:

     for (NSString *key in selectedFiltersByUser) {
    [filters_data setObject:key forKey:@"key"];
    [filters_data setObject:selectedFiltersByUser[key] forKey:@"value"];

    // Added filter selected id's into Array for all query_params
    [query_params addObject:filters_data];
}
  

Но при добавлении этого NSMutableDictionary в NSMutableArray это не заменяет последний объект, и я получаю это в query_params:

     {
       key: category_id,
       value: XXX
   },
   {
    key: category_id,
    value: XXX
   },
   {
    key: category_id,
    value: XXX
   }
  

Мне нужно это:

 {
       key: category_id,
       value: XXX
   },
   {
    key: sort,
    value: last_updated_asc
   },
   {
    key: status,
    value: rejected_by_seller
   }
  

Я не знаю, как заменить последний добавленный объект.

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

1. попробуйте [NSDictionary alloc] init] в цикле for, а затем добавьте данные.

2. В цикл? Но я завершаю цикл. Я создал новый NSMutableDictionary для каждого элемента, а затем добавил в другую структуру? @NiravKotecha

3. да, в цикл.

4. когда вы выполняете инициализацию из цикла, каждый раз он переходит во внутренний цикл, и ключ остается тем же, поэтому он перезаписывается новым значением. если вы запустите цикл, он создаст новый.

5. Спасибо. Это были мои проблемы. Мне нужно создать NSMutableDictionary в цикле. @NiravKotecha

Ответ №1:

попробуйте [NSMutableDictionary alloc] init] в цикле for, а затем добавьте данные.

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

 for (NSString *key in selectedFiltersByUser) {

    //INIT HERE YOUR DICTIONARY
    NSMutableDictionary *filters_data = [NSMutableDictionary alloc] init];

    [filters_data setObject:key forKey:@"key"];
    [filters_data setObject:selectedFiltersByUser[key] forKey:@"value"];

    // Added filter selected id's into Array for all query_params
    [query_params addObject:filters_data];
}
  

Ответ №2:

Добавление словаря в массив не копирует словарь. Он хранит ссылку на объект (словарь) в массиве, поэтому ссылка на идентичный словарь добавляется каждый раз.

Перезапись содержимого словаря изменяет идентичный словарь, который хранится в массиве несколько раз.

Вы должны каждый раз создавать новый словарь. Нет причин создавать изменяемый объект.

Ответ №3:

Как указывалось в комментариях, ваша проблема связана с ссылочной семантикой коллекций Objective-C, то есть они содержат ссылки на существующие объекты, а не их копии. Итак, если вы добавляете одно и то же NSMutableDictionary несколько раз в NSMutableArray , как это делает ваш код, вы в конечном итоге получаете, что каждый элемент массива является ссылкой на один и тот же словарь. Уже предлагаемое простое исправление заключается в том, чтобы выделить словарь внутри вашего цикла:

 for (NSString *key in selectedFiltersByUser)
{
   NSMutableDictionary *filters_date = [NSMutableDictionary new];
   [filters_data setObject:key forKey:@"key"];
   [filters_data setObject:selectedFiltersByUser[key] forKey:@"value"];
   [query_params addObject:filters_data];
}
  

Однако вы можете упростить это и вообще избежать проблемы. Вы уже индексируете selectedFiltersByUser , вы также можете индексировать filters_data аналогичным образом, предоставляя вам:

 for (NSString *key in selectedFiltersByUser)
{
   NSMutableDictionary *filters_date = [NSMutableDictionary new];
   filters_data[@"key"] = key;
   filters_data[@"value"] = selectedFiltersByUser[key];
   [query_params addObject:filters_data];
}
  

но это все равно оставляет вас с выделением, которое вы можете удалить, используя литерал словаря:

 for (NSString *key in selectedFiltersByUser)
{
   NSDictionary *filters_date
      = @{ @"key": key,
           @"value": selectedFiltersByUser[key]
         };
   [query_params addObject:filters_data];
}
  

Теперь там выделение обрабатывается компилятором автоматически, и вы получаете NSDictionary . Последний вариант — полностью отказаться filters_date :

 for (NSString *key in selectedFiltersByUser)
{
   [query_params addObject:@{ @"key": key,
                              @"value": selectedFiltersByUser[key]
                            }
   ];
}
  

Вы можете обнаружить, что использование литералов словаря (и массива) помогает вам избежать ошибок выделения и создания изменяемых структур, когда они не требуются. HTH