Добавление NSMutableArray к другому из цикла, кажется, создает дубликаты - PullRequest
0 голосов
/ 16 февраля 2012

Я анализирую NSDictionary json-кодированных событий и помещаю их в двумерное NSMutableArray в зависимости от их месяца - для отображения в виде секционированной таблицы.

Поскольку я добавляю элементы в массив, а затем помещаю этот массив в массив (event_container) в цикле, event_container показывает правильное количество массивов, однако все они представляются дубликатами последней итерации так что все содержимое event_container - это один и тот же массив.

Я считаю, что это потому, что это указатель и / или не выпускается. Я не уверен в правильном подходе к этому или, возможно, даже к лучшему решению. Я использую ARC.

int month = 0;
int current_month = 0;
int counter = 0;

event_container = [[NSMutableArray alloc] init];

temp_array = [[NSMutableArray alloc] init];


for (NSDictionary *result in results)
{

    NCEvent *anEvent = [[NCEvent alloc] init];

    anEvent.title = [result objectForKey:@"title"];
    anEvent.startdate = [result objectForKey:@"startdate"];
    anEvent.enddate = [result objectForKey:@"enddate"];

    NSDateFormatter *importDate = [[NSDateFormatter alloc] init];
    [importDate setDateFormat:@"yyyy-M-d H:m:ss"];
    anEvent.dateStart = [importDate dateFromString:anEvent.startdate];
    anEvent.dateEnd = [importDate dateFromString: anEvent.enddate];

    NSDateFormatter *exportDate = [[NSDateFormatter alloc] init];
    [exportDate setDateFormat:@"d"];
    anEvent.text_date = [exportDate stringFromDate: anEvent.dateStart];

    NSDateFormatter *exportMon = [[NSDateFormatter alloc] init];
    [exportMon setDateFormat:@"MMM"];
    anEvent.text_mon = [exportMon stringFromDate: anEvent.dateStart];

    NSDateFormatter *monthInt = [[NSDateFormatter alloc] init];
    [monthInt setDateFormat:@"M"];
    month = [[monthInt stringFromDate: anEvent.dateStart] intValue];

    if(counter == 1){                           //first month
        current_month = month;
        NSLog(@"I'm the first month: %i", month); 
        [temp_array addObject:anEvent];

    }
    else if(month > current_month){             //new month
        NSLog(@"This is a new month");                    
        current_month = month;

        //add the events array to events container and reset the events array
        [self.event_container addObject: temp_array];

        [temp_array removeAllObjects];

        [temp_array addObject:anEvent];

    }
    else{
        NSLog(@"Same Month");                   //same month
        [temp_array addObject:anEvent];


    }

    NSLog(@"Event month integer: %i", month);

    anEvent = nil;

    counter++;

}

Эти массивы объявлены как свойства:

@property (nonatomic, retain) NSMutableArray *event_container;
@property (nonatomic, retain) NSMutableArray *temp_array;

Ответы [ 3 ]

2 голосов
/ 16 февраля 2012

В строке:

[self.event_container addObject: temp_array];

Вы всегда добавляете один и тот же экземпляр temp_array к self.event_container. Вот почему вы видите, что один и тот же массив дублируется много раз.

Вы можете решить эту проблему, например, следующим образом:

-Добавить следующее перед циклом for

for (int i = 0; i < 12; i++) {
    [event_container addObject:[NSMutableArray array]];
}
for (NSDictionary *result in results)
...

-Remove

if(counter == 1){                           //first month
     current_month = month;
     NSLog(@"I'm the first month: %i", month); 
     [temp_array addObject:anEvent];
}

-и изменить код, который идет после этого на:

tmp_array = [event_container objectAtIndex:month];
[temp_array addObject:anEvent];
1 голос
/ 16 февраля 2012

Ваши подозрения о том, что массив является указателем, в основном верны. Проблема в том, что ваш temp_array не так временен - ​​это фактически один и тот же объект массива каждый раз в вашем цикле.

Вы создаете его вне цикла, и всякий раз, когда вы отправляете его addObject: или removeAllObjects, это влияет на то, что вы уже добавили туда.

Ключевая часть, однако, заключается в том, что когда вы добавляете temp_array к event_container, это точно такой же объект. Это не копируется; массив event_container просто получает указатель на temp_array. Когда вы добавляете это снова, это то же самое. Поскольку event_container содержит целую кучу указателей, вы в конечном итоге смотрите на один и тот же объект, когда осматриваете его.

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

Быстрая демонстрация:

NSMutableArray * container = [NSMutableArray array];
NSMutableArray * temp = [NSMutableArray array];

int i;
for( i = 0; i < 5; i++ ){
    [temp addObject:[NSNumber numberWithInt:i]];
    [container addObject:temp];    // Doesn't copy; just adds pointer to temp
    [temp removeAllObjects];
}
// Inspecting container now, we find that it has five arrays, all empty.
NSLog(@"%@", container);
0 голосов
/ 16 февраля 2012

temp_array - это тип указателя (как и все объекты в цели c). Поэтому с этим вызовом:

[self.event_container addObject: temp_array];

... вы добавляете указатель на этот объект в event_container. Вы не создаете новый массив, просто добавляете несколько указателей на один и тот же объект. Скорее всего, вам нужно добавить (указатель на) копию объекта, например:

[self.event_container addObject: [temp_array mutableCopy]];

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...