NSMutableArray addObject: - [__ NSArrayI addObject:]: непризнанный селектор, отправленный экземпляру

Я попытался инициализировать мой NSMutableArray 100 способов с воскресенья, и НИЧЕГО не работает для меня. Я попытался установить его равным вновь выделенному и инициализированному NSMutableArray, просто выделив, инициализируя переменную сам по себе, каждую комбинацию, о которой я мог думать, и всегда такой же результат.

Здесь код:

Object.h

NSMutableArray *array;

@property (copy) NSMutableArray *array;

Object.m

@synthesize array;

if ( self.array ) {
    [self.array addObject:anObject];
}
else {
    self.array = [NSMutableArray arrayWithObjects:anObject, nil];
}

ПРИМЕЧАНИЕ. В отладочном "anObject" NOT nil во время выполнения...

Я тестировал anObject, и это инициализация работает нормально, но я продолжаю получать ошибку ниже, когда я пытаюсь добавить объект: to self.array.

2010-07-10 11: 52: 55.499 MyApp [4347: 1807] - [__ NSArrayI addObject:]: непризнанный селектор отправлен в экземпляр 0x184480

2010-07-10 11: 52: 55.508 MyApp [4347: 1807] *** Завершение приложения из-за неперехваченного исключения 'NSInvalidArgumentException', причина: '- [__ NSArrayI addObject:]: непризнанный селектор, отправленный в экземпляр 0x184480'

Кто-нибудь знает, что происходит не так?

Ответ 1

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

//@property (copy) NSMutableArray *array;
@property (nonatomic, copy) NSMutableArray *array; //overridden method is non-atomic as it is coded and should be reflected here.

Если вы хотите использовать (копировать) на изменяемом объекте, вы должны переопределить метод "setter" следующим образом:

- (void)setArray:(NSArray *)newArray {

    if ( array != newArray ) { 
        [array release];
        array = [newArray mutableCopy];
//      [array retain]; // unnecessary as noted by Georg Fritzsche
    }

    return;
}

ПРИМЕЧАНИЕ. Вы получите предупреждение компилятора: Несовместимый Objective-C тип инициализации структуры NSArray *, ожидаемый 'struct NSMutableArray *' Я решил объявить параметр newArray как (NSArray *), потому что вам предоставляется гибкость чтобы любой массив прошел и правильно скопировал вашу переменную (NSMutableArray *). Если вы хотите объявить параметр newArray как (NSMutableArray *), вам все равно нужно оставить метод mutableCopy на месте, чтобы получить желаемые результаты.

Приветствия Георгу! Z @K!

Ответ 2

Синтезированный сеттер для @property (copy) отправляет в массив сообщение copy, что приводит к неизменяемой копии.

У вас нет выбора, кроме как реализовать здесь установщика, подробный в руководстве Objective-C.

Ответ 3

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

Моя ошибка была в...

@property (copy) NSMutableArray *array;

он должен был быть...

@property (retain) NSMutableArray *array;

Ошибка не происходила в том, как я выполнял свой код, а скорее в том, как anObject пытался "скопировать" массив NSMutableArray.

Как мы все знаем...

mutableArray = [mutableArray copy];

не всегда (или когда-либо, по моему опыту), равным...

mutableArray = [mutableArray mutableCopy];

И это стало причиной моей проблемы. Просто переключив @property из (copy) в (сохранить), я решил свою проблему.

Ответ 4

Я получал ту же ошибку, хотя мои свойства были сильными (с использованием ARC), и я выделил массив с помощью NSMutableArray.

Что происходило, так это то, что я архивировал измененный массив (так как он содержит пользовательские объекты) для будущего использования, а при его расшифровке он возвращает неизменяемую копию.

Надеюсь, что это поможет кому-то там.

Ответ 5

Имейте некоторые индексы (в массив данных в другом месте) и хотите иметь их в численном порядке (по уважительной причине). Сбой до добавления mutableCopy в конец. Полностью озадачен, пока не напомнил, что использование Objective-C literal @[] возвращает не изменяемый массив.

NSMutableArray *a = [@[@(self.indexA), @(self.indexB)] mutableCopy];
NSLog(@"%@", a);
[indexArray sortUsingComparator: ^(NSNumber *obj1, NSNumber *obj2) {
    return [obj1 compare:obj2];
}];
NSLog(@"%@", a);

Thanx, Zak!

Ответ 6

Я был укушен этим исключением за опечатку, которую я сделал, может быть, это спасет кого-то 5 мин. своего времени:

Я написал:

NSMutableArray *names = [NSArray array];

вместо:

NSMutableArray *names = [NSMutableArray array];

У компилятора нет проблем с этим, потому что NSMutableArray также является NSArray, но он сбой при попытке добавить объект.

Ответ 7

Ошибка возникла из-за попытки добавить объект к типу NSMutableArray, который фактически указывал на объект NSArray. Этот тип сценария показан в некотором демо-коде ниже:

NSString *test = @"test";
NSMutableArray *mutableArray = [[NSMutableArray alloc] init];
[mutableArray addObject:test];
NSArray *immutableArray = [[NSArray alloc] init];
mutableArray = immutableArray;
[mutableArray addObject:test]; // Exception: unrecognized selector

Из приведенного выше кода легко видеть, что тип подкласса присваивается классу суперкласса. Например, в Java это немедленно будет помечено как ошибка (ошибка преобразования между типами), и проблема будет решена довольно быстро. Чтобы быть честным с Objective-C, предупреждение при попытке выполнить несовместимое назначение, однако, это просто просто не кажется достаточным иногда, и результат может быть настоящей болью для разработчиков. К счастью, на этот раз, я сам не сам переносил большую часть этой боли: P

Ответ 8

Это исключение может произойти, если один из объектов массива имеет значение null.