NSSet к NSArray, вызывающему вызывание objectAtIndex? - PullRequest
43 голосов
/ 24 января 2012

Я пытаюсь обновить MKMapView, удалив все аннотации за пределами видимой области, а также добавив и удалив некоторые аннотации внутри видимой области. Это мой код:

NSSet *visibleAnnotations = [mapView annotationsInMapRect:[mapView visibleMapRect]];
NSSet *allAnnotations = [NSSet setWithArray:[mapView annotations]];
NSMutableSet *nonVisibleAnnotations = [NSMutableSet setWithSet:allAnnotations];
[nonVisibleAnnotations minusSet:visibleAnnotations];
[mapView removeAnnotations:(NSArray *)nonVisibleAnnotations];

NSMutableSet *newAnnotations = [NSMutableSet setWithArray:[_zoomLevels objectAtIndex:clusterLevel]];
[newAnnotations minusSet:visibleAnnotations];
[mapView addAnnotations:(NSArray *)newAnnotations];

Это дает мне ошибку - [__NSCFSet objectAtIndex:]: нераспознанный селектор, отправленный экземпляру 0x13cd40 после последней строки, в которой я приводил newAnnotations к NSArray, затем добавляю аннотации. Есть ли что-то в приведении массива к набору, который вызывает это? Если так, есть ли способ обойти это?

Ответы [ 5 ]

174 голосов
/ 24 января 2012

Несмотря на то, что вы преобразуете NSMutableSet в NSArray, это простое приведение не заставит класс NSSet отвечать на сообщения NSArray.Вы должны заполнить фактический NSArray элементами NSSet следующим образом:

NSArray *array = [theNsSet allObjects];
6 голосов
/ 24 января 2012

Приведение объекта NSSet к NSArray не будет делать ничего другого, что заставит компилятор думать, что объект является NSArray. На самом деле, объект является NSSet объектом, и попытка использовать его как NSArray приведет к ошибке.

Другой способ убедиться в том, что приведение - это просто уловка с указателями, а не с указанными объектами, которые остаются неизменными.

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

В любом случае, в вашем конкретном случае вы можете попытаться получить доступ к элементам NSSet через NSArray, используя:

 [newAnnotations allObjects]

Это

Возвращает массив, содержащий членов набора, или пустой массив, если в наборе нет членов.

5 голосов
/ 10 июня 2014

Другой способ получить NSMutableArray из NSSet -

NSMutableArray * array= [[set allObjects] mutableCopy];

Кроме того, решение, предложенное satzkmr, выдает предупреждение «Несовместимый указатель». (Извините, что написал это здесь, у меня недостаточно репутации, чтобы комментировать).

3 голосов
/ 03 июля 2012

Да, вы должны сначала сохранить набор в массив, как этот ...

NSMutableArray *array = [NSMutableArray arrayWithArray:[set allObjects]];
1 голос
/ 13 ноября 2013

Следующий шаг для преобразования NSSet в NSArray или NSMutableArray,

NSSet *airports = [NSSet setWithObjects:@"Chennai",@"Mumbai",@"Delhi", nil];
NSLog(@"Set Elemets Before Move:%@", airports);
NSMutableArray *movedAirports = [airports allObjects];
NSLog(@"Array Elements After Moving from Set:%@", movedAirports);
...