NSArray глубокое копирование вызывает сбой - PullRequest
0 голосов
/ 07 октября 2011

Я уже давно смотрю на этот код, но не могу понять, что в мире не так.У меня есть класс с именем SortFilteringController, который управляет различными фильтрами, которые у меня есть в системе (внутренний фильтр, открытый фильтр, параметры сортировки и т. Д.).Каждый из них хранится в массиве.Итак, у меня есть метод сравнения, который в основном берет любой из этих массивов и сбрасывает их с некоторыми новыми данными.

Например, setInternalFilter просто вызывает его.

- (void) setInternalFilterTerms : (NSArray*) filterTerms {

    [self resetArray: &_internalFilters withNewData:filterTerms];
}

Определениеиз resetArray, это просто для того, чтобы сбросить существующий (освободить его) и скопировать новые данные.

- (void) resetArray: (NSMutableArray**) oldArray withNewData : (NSArray*) newData {

    if (*oldArray != nil) {
        [*oldArray release];
    }


    NSMutableArray* newArray = [[NSMutableArray alloc] initWithArray:newData copyItems:YES];
    *oldArray = [newArray retain];
    [newArray release];    

}

Но моя проблема в том, что я получаю сбой в методе сброса.Не в симуляторе, только на устройстве.

Thread 0 Crashed:
0   libsystem_kernel.dylib          0x331a3a1c __pthread_kill + 8
1   libsystem_c.dylib               0x3404c3b4 pthread_kill + 52
2   libsystem_c.dylib               0x34044bf8 abort + 72
3   libstdc++.6.dylib               0x30e4fa64 __gnu_cxx::__verbose_terminate_handler() + 376
4   libobjc.A.dylib                 0x30fda06c _objc_terminate + 104
5   libstdc++.6.dylib               0x30e4de36 __cxxabiv1::__terminate(void (*)()) + 46
6   libstdc++.6.dylib               0x30e4de8a std::terminate() + 10
7   libstdc++.6.dylib               0x30e4df5a __cxa_throw + 78
8   libobjc.A.dylib                 0x30fd8c84 objc_exception_throw + 64
9   CoreFoundation                  0x33e5f1b8 -[NSObject(NSObject) doesNotRecognizeSelector:] + 96
10  CoreFoundation                  0x33e5e642 ___forwarding___ + 502
11  CoreFoundation                  0x33dd5178 _CF_forwarding_prep_0 + 40
12  CoreFoundation                  0x33dcb156 -[NSArray initWithArray:range:copyItems:] + 366
13  CoreFoundation                  0x33dcafce -[NSArray initWithArray:copyItems:] + 54
14  Wine DB 1.1                     0x001b6a2a -[SortFilterController resetArray:withNewData:] (SortFilterController.m:1310)
15  Wine DB 1.1                     0x001b4188 -[SortFilterController setInternalFilterTerms:] (SortFilterController.m:733)

Я использую xcode 4.2 с iOS 5.0 GM seed.Мое устройство все еще работает 4.1.3.Но это не должно иметь значение правильно?И ошибка "не делает распознавания выбора".Как странно это.

Спасибо.

Ответы [ 2 ]

1 голос
/ 07 октября 2011

Проверьте, если oldArray == newData. Вы заметите, что идиома по умолчанию для операции над множествами в Objective-C такова:

-(void) setFoo:(NSThing *)newThing
{
    [newThing retain];
    [thing release];
    thing = newThing;
}

Если newThing == вещь, и вы удаляете текущую вещь, то вы вполне можете заставить ее вызывать деструктор. Таким образом, вы всегда делаете в первую очередь.

Так что вы можете освободить те самые объекты, которые хотите скопировать. И, используя новейшие сборщики мусора, устройство может убирать быстрее, чем симулятор. Ошибки есть на обеих платформах, но неопределенный характер менеджера памяти может заставить вас думать, что он временный.

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

0 голосов
/ 07 октября 2011

Может ли быть так, что объекты, хранящиеся в массиве, не соответствуют протоколу NSCopying? Поэтому, когда инициализатор пытается вызвать метод copy для них, они просто не знают, как с этим справиться?

...