Unrecognized selector with array objects. - objective-c

The NSImageView objects once in the array become strings. How to I convert them into NSImageView to avoid unrecognized selector error generated by the last line?
NSArray *array = [NSArray arrayWithObjects: #"chip1”, #"chip2” nil],
for (id image in array) {
[image setImage: nil];
}

The #"..." notation in Objective-C is shorthand for creating an NSString. In the above code example, you're creating an array of NSString's, which is why you're getting the unrecognized selector error when you call setImage:.
Assuming chip1 and chip2 are instances of NSImageView, you should be doing the following:
NSArray *array = [NSArray arrayWithObjects:chip1, chip2, nil];
You can avoid issues like this in future, by using Objective-C Generics when defining your array:
NSArray <NSImageView*>*array = [NSArray arrayWithObjects:chip1, chip2, nil];
This would give a compiler error if you tried to add a class other that NSImageView to the array.

Related

NSDictionary of uninitialized objects?

How can I store an uninitialized object in an NSDictionary?
I think I would do it like this, but I’m not certain that it’s a good approach:
NSDictionary *dict = [[NSDictionary alloc] initWithObjectsAndKeys:
[MyObject1 alloc], #"myObject1",
[MyObject2 alloc], #"myObject2"
, nil];
MyObject1 *object = [dict objectForKey:#"myObject1"];
[object init];
Any help would be appreciated.
What you need is to store mutable objects inside the dictionary. Doing this you will be able to modify them after the insertion, because an immutable dictionary doesn't allow to insert a new object.
If for "uninitialized" you mean that the object has only been created with alloc, without init, that's deprecable because init may return a different object from the one returned with alloc. So just store them like you're doing it, and when you need to modify them call the accessors:
NSDictionary *dict = #{ #"myObject1" : [MyObject1 new] , #"myObject2" : [MyObject2 new] };
dict[#"myObject1"].someProperty= someValue;
If your MyObject1 class is immutable, then you have to use a mutable dictionary.

[__NSArrayI replaceObjectAtIndex:withObject:]: unrecognized selector sent to instance

I have a NSMutableArray, which I need to chance its values, but I have this error:
[__NSArrayI replaceObjectAtIndex:withObject:]: unrecognized selector sent to instance 0x5291db0
This is the declaration of my NSMutableArray:
NSMutableArray *selectedOptions = [NSArray arrayWithObjects:[NSNumber numberWithInteger:0], nil];
Then, I'm using replaceObjectAtIndex method, of this way:
[self.selectedOptions replaceObjectAtIndex:0 withObject:[NSNumber numberWithInteger:1]];
But I get, that error, and I'm using NSMutableArray.
Thanks
You are creating a regular non-mutable NSArray. Your code should be
NSMutableArray *selectedOptions = [NSMutableArray arrayWithObjects:[NSNumber numberWithInteger:0], nil];
Objective C is very dynamic, so it does not catch this mistake at compile time.
You need to initialize your NSMutableArray by doing
NSMutableArray *selectedOptions = [NSMutableArray alloc] init];
By initializing it with NSArray, you can no longer use the repalceObjectAtIndex:withObject: method and that's the cause of your problem.
After initializing your NSMutableArray with the line above, simply add objects to it with the addObject method.

[__NSCFString superview]: unrecognized selector sent to instance

I am trying to copy a NSMutableArray* into NSArray*, but it does not works and it generates a [__NSCFString superview]: unrecognized selector sent to instance error . Here is the code:
//where gc is a NSDictionary*, recentKey is a NSString*, and _objects is a NSArray*
//gc is an singleton is used to save chache data, with NSKeyedUnarchiver class
//_objects is used to reload the UITableView's data
NSArray *savedNews = [[NSArray alloc] initWithArray:[gc objectForKey:recentkey]];
//this not works...why??
_objects = [[NSArray alloc] initWithArray:savedNews];
Resolution:
Yes, as Herman suggests, the error was external. The savedNews Array was using a class with NSEncoding with an error:
- (void)encodeWithCoder:(NSCoder *)encoder {
//...where element was NSString* and not "UIImageView"
// element should be imgView
if (imgView) [encoder encodeObject:element forKey:#"imgView"];
}
Thanks for all guys.
Somewhere in your App is the superview of an NSString object fetched.
I guess that you assigned an NSString object to something where a UIView is expected.
Could be something like:
someButton.textLabel = someString; // wrong - but should generate a compiler warning
instead of
someButton.textLabel.text = someString; // correct
This is not directly related to your array issue.
First, check what the object in the dictionary is for that key.
NSLog(#"GC Object type for recentkey:%#", [[gc objectForKey:recentkey] class]);
You can only pass an NSArray to initWithArray:
So if that object isn't already an NSArray but you want that object to be IN an array. The do this..
id obj = [gc objectForKey:recentkey]; //Because I have no idea what this is
NSArray *savedNews = [NSArray arrayWithObject:obj];

NSSet to NSArray casting calling objectAtIndex?

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?
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];
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.
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).
Yes, you should first store the set into an array like this...
NSMutableArray *array = [NSMutableArray arrayWithArray:[set allObjects]];
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);
NSArray *array = [sets allObjets];

Is this a correct declaration of an Array in Objective c?

NSArray *arr=[[[NSArray alloc]autorelease]autorelease];
Close, but no cigar.
If you want an autoreleased NSArray, you'd need to use:
NSArray *arr = [[NSArray alloc] init] autorelease];
That said, this will simply get you an empty immutable array, so you'll most likely want to populate it via one of the initWithObjects: style methods. (See the full NSArray class reference for more information.)
Or you can just declare it like this:
[NSArray array];
This gives you an autoreleased instance of the array.