NSSet to NSArray casting calling objectAtIndex?
Asked Answered
D

6

50

I'm trying to update an MKMapView by removing all annotations outside the visible area, and adding and removing some annotations inside the visible area. This is my code:

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

This gives me the error -[__NSCFSet objectAtIndex:]: unrecognized selector sent to instance 0x13cd40 after the final line in which I cast newAnnotations to an NSArray then add the annotations. Is there something about casting an array to a set that causes this? If so, is there a way round it?

Dentate answered 24/1, 2012 at 10:13 Comment(0)
M
187

Despite you're casting NSMutableSet to NSArray, that simple casting won't make NSSet class respond to NSArray's messages. You have to fill an actual NSArray with the elements of the NSSet like this:

NSArray *array = [theNsSet allObjects];
Migdaliamigeon answered 24/1, 2012 at 10:16 Comment(4)
allObjects changes the order.So objectAtIndex may not return the intended.Mestizo
@Mestizo Non sequitur. A set is not ordered.Migdaliamigeon
The suggested solution here doesn't work for me... [theNSSet allObjects] simply adds the NSSet as an object inside an NSArray, which is a fail, because I don't need an NSSet INSIDE an NSArray, I need an NSArray FROM the contents of the NSSetConsuelaconsuelo
@LogicsaurusRex allObjects returns an Array containing the Set's members. This solution should work for you.Jacinda
B
6

Casting an NSSet object to NSArray will not do anything else that tricking the compiler into thinking that the object is an NSArray. Actually, the object is an NSSet object and trying to use it as an NSArray will produce failure.

Another way to see it is that casting is just a trick on pointers, not on the pointed-to objects, that remain unaltered.

Casting is only safe in certain cases, like when you cast from a derived class to a base class; or when you are absolutely sure that the underlying object real type is consistent with the type you are casting it to.

Anyway, in your specific case, you might try to access the NSSet elements through an NSArray by using:

 [newAnnotations allObjects]

This

Returns an array containing the set’s members, or an empty array if the set has no members.

Bureau answered 24/1, 2012 at 10:15 Comment(0)
G
5

Another way to get an NSMutableArray from an NSSet is

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

Also, the solution proposed by satzkmr gives you an "Incompatible pointer" warning. (Sorry to write this here, I don't have enough reputation to comment).

Glioma answered 10/6, 2014 at 19:5 Comment(0)
N
3

Yes, you should first store the set into an array like this...

NSMutableArray *array = [NSMutableArray arrayWithArray:[set allObjects]];
Niggle answered 3/7, 2012 at 6:45 Comment(0)
K
1

Following Step to be followed to convert a NSSet into NSArray or 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);
Keelin answered 13/11, 2013 at 10:0 Comment(0)
S
-1
NSArray *array = [sets allObjets];
Strongbox answered 27/11, 2019 at 13:3 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.