2012-01-24 8 views
37

Estoy tratando de actualizar un MKMapView eliminando todas las anotaciones fuera del área visible y agregando y eliminando algunas anotaciones dentro del área visible. Este es mi código:NSSet a NSArray casting calling objectAtIndex?

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]; 

Esto me da el error - [__ NSCFSet objectAtIndex:]: Selector no reconocido enviado a la instancia 0x13cd40 después de la última línea en la que yo echo newAnnotations a un NSArray a continuación, añadir las anotaciones. ¿Hay algo acerca de lanzar una matriz a un conjunto que causa esto? Si es así, ¿hay una forma de evitarlo?

Respuesta

160

A pesar de que estas lanzando NSMutableSet a NSArray, que la fundición simple no hará NSSet responden a los mensajes de clase NSArray 's. Usted tiene que llenar un real NSArray con los elementos de la NSSet como este:

NSArray *array = [theNsSet allObjects]; 
+4

allObjects cambia el orden. Por lo tanto, objectAtIndex puede no devolver el deseado. – Vignesh

+10

@Vignesh Non sequitur. Un conjunto no está ordenado. –

+0

La solución sugerida aquí no funciona para mí ...'[theNSSet allObjects]' simplemente agrega el NSSet como un objeto dentro de un NSArray, que es un error, porque no necesito un NSSet INSIDE un NSArray, necesito un NSArray FROM los contenidos del NSSet –

5

Lanzar un objeto NSSet a NSArray no hará otra cosa que engañar al compilador haciéndole creer que el objeto es un NSArray. En realidad, el objeto es un objeto NSSet e intenta usarlo como NSArray producirá un error.

Otra forma de verlo es que la fundición es solo un truco en los punteros, no en los objetos puntiagudos, que permanecen inalterados.

La conversión solo es segura en ciertos casos, como cuando se lanza de una clase derivada a una clase base; o cuando esté absolutamente seguro de que el tipo real del objeto subyacente es consistente con el tipo al que lo está enviando.

De todos modos, en su caso específico, puede intentar acceder a los elementos nsset a través de un NSArray mediante el uso de:

[newAnnotations allObjects] 

This

Devuelve una matriz que contiene los miembros del conjunto, o un vacío array si el conjunto no tiene miembros.

3

Sí, primero tiene que guardar el conjunto en una serie como esta ...

NSMutableArray *array = [NSMutableArray arrayWithArray:[set allObjects]]; 
1

Siguiendo paso a ser seguido de convertir un NSSet en NSArray o 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); 
5

Otra manera de obtener una NSMutableArray de un NSSet es

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

Además, la solución propuesta por satzkmr le da una advertencia de "puntero incompatible". (Perdón por escribir esto aquí, no tengo suficiente reputación para comentar).