Objective C: как проверить, является ли переменная NSArray или NSMutableArray

По некоторым причинам у меня были проблемы с выполнением проверки по сравнению с DBNull. Значение, таким образом, я сделал немного отличающиеся вещи и усилил свойство в объекте DataRow:

if (row.IsNull["fooColumn"])
{
   value = string.Empty();
}
{
else
{
   value = row["fooColumn"].ToString;
}
21
задан Dan Rosenstark 27 October 2011 в 13:47
поделиться

4 ответа

* Обратите внимание, что реализация NS {, Mutable} Array изменилась с момента написания этого ответа. В результате isKindOfClass: теперь работает. На каких платформах, где и когда, я не знаю.

Пока это не будет задокументировано как безопасное, я бы настоятельно рекомендовал НЕ писать код, который пытается определить, является ли коллекция изменчивой или неизменной. . Даже если бы это было безопасно, такой шаблон проектирования почти всегда указывает на серьезный недостаток дизайна.

(Для тех, у кого есть доступ) Подан rdar: // 10355515 с просьбой пояснить.


Рассмотрим:

int main (int argc, const char * argv[]) {
    NSArray *array = [NSArray arrayWithObjects: [NSObject new], nil];
    NSMutableArray *mutableArray = [NSMutableArray arrayWithObjects: [NSObject new], nil];

    NSLog(@"array's class: %@", NSStringFromClass([array class]));
    NSLog(@"mutableArray's class: %@", NSStringFromClass([mutableArray class]));

    NSLog(@"array responds to addObject: %@", 
          [array respondsToSelector: @selector(addObject:)] ? @"YES" : @"NO");

    return 0;
}

(I ' m, используя непустые массивы, потому что пустой NSArray достаточно распространен, чтобы Какао предлагает единственный общий экземпляр в качестве оптимизации.)

array's class: NSCFArray
mutableArray's class: NSCFArray
array responds to addObject: YES

Т.е. ни -isKindOfClass: , ни проверка реализации реализации addObject: будет работать.

Короче говоря, вы не можете отличить NSArray от NSMutableArray. Это сделано намеренно и во многом так, как предполагалось. Это также верно для NSString , NSDictionary и NSSet (все они имеют изменяемый подкласс ).

Это может произойти. как сюрприз. Однако на самом деле

32
ответ дан 29 November 2019 в 20:28
поделиться

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

Это может быть опасно. Если класс позволяет вам изменять массив, у него будет другой метод доступа или мутатор.

Если у вас есть класс-друг, которому требуется изменяемый доступ к переменной myInternalObjects, то объявите специальную категорию адаптера, которую импортирует только класс-друг. с помощью такого метода, как

- (NSMutableArray *)mutableInternalObjectsArray;

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

6
ответ дан 29 November 2019 в 20:28
поделиться

См. Метод NSObject -class :

NSLog(@"myUnknownArray is of type: %@", [myUnknownArray class]);

Вы также можете напрямую проверить с помощью + class метод:

BOOL isMutableArray = [myUnknownArray isKindOfClass:[NSMutableArray class]];
0
ответ дан 29 November 2019 в 20:28
поделиться

Вы должны использовать:

[yourArray isKindOf: [NSArray class]]

, поскольку простое сравнение классов может завершиться неудачно, потому что ваш массив, вероятно, не является NSArray, а относится к другому низкоуровневому типу. Вы также можете проверить, отвечает ли ваш массив нужным вам методам.

[yourArray respondsToSelector: @selector(addObject:)]
-1
ответ дан 29 November 2019 в 20:28
поделиться