+ (NSString *)numberMatching: (NSString *)number and: (NSString *)secondNumber
{
NSString *returnNumber;
if ([number isEqualToString:secondNumber]) {
returnNumber = number;
} else {
NSMutableArray *validNumber = [[self validNumbers] copy];
[validNumber removeObject:number];
[validNumber removeObject:secondNumber];
returnNumber = validNumber[0];
}
return returnNumber;
}
In case it matters, here is the code for validNumber:
+ (NSArray *)validNumbers
{
static NSArray *validNumbers = nil;
if (!validNumbers) validNumbers = #[#"one",#"two",#"three"];
return validNumbers;
}
When run, I get the following error:
-[_NSArrayI removeObject:]: unrecognized selector sent to instance 0x1ed60f00 ... Terminating app due to uncaught exception
'NSInvalidArgumentException', reason: '-[_NSArrayI removeObject:]:
unrecognized selector sent to instance 0x1ed60f00'
That would seem to indicate that removeObject is not a valid method for an NSMutableArray, but it is valid.
Essentially, what I want to do is this: if the two arguments match, I want to return the value. If they don't match, I want to return the third possibility (doesn't match either argument).
Because validNumber is an NSArray. You can't remove (or add) objects from an NSArray. Use NSMutableArray and mutableCopy instead:
NSMutableArray *validNumber = [[self validNumbers] mutableCopy];
[validNumber removeObject:number];
[validNumber removeObject:secondNumber];
When you send the copy message to an NSArray, the copy you get is also an NSArray instance and you can't remove objects from an immutable array. In order to get a mutable copy you need to send the mutableCopy message:
NSMutableArray *validNumber = [[self validNumbers] mutableCopy];
Related
A bit new to Objective-C, so please bear with me.
Firstly, I'm using the FMDB library for SQLite management.
I'm populating an NSMutableDictionary using the following method:
//....
while([effectivenessResults next]) //this loops through the results of a query (verified that this works)
{
NSMutableArray *dFactors = [[NSMutableArray alloc]init];
if([resultDict objectForKey:[effectivenessResults stringForColumn:#"tName"]])
{
dFactors = [resultDict objectForKey:[effectivenessResults stringForColumn:#"tName"]];
}
NSNumber *effectivenessValToAdd = [NSNumber numberWithDouble:[effectivenessResults doubleForColumn:#"dFactor"]/100];
[dFactors addObject:[NSMutableString stringWithFormat:#"%#",effectivenessValToAdd]];
[resultDict setObject:dFactors forKey:[effectivenessResults stringForColumn:#"tName"]];
}
I'm returning the array properly (I have verified this). Then, I am accessing this NSMutableDictionary elsewhere, using the follwing method:
for(id type in tEffect) //tEffect is the NSMutableDictionary, returned from the previous code (there known as resultDict)
{
effectivenessString = [self getEffectivenessString:[tEffect objectForKey:type]];
tInfo = [NSMutableString stringWithFormat:#"%#", [tInfo stringByAppendingFormat:#"%#: %#\n", type, effectivenessString]];
}
which calls the following two methods:
-(NSMutableString *)getEffectivenessString:(NSNumber *) numberPassedIn
{
double dFactor = [numberPassedIn doubleValue];
//adds the above value to a string, this will not affect anything
}
and
-(NSNumber *) listProduct: (NSMutableArray *)listOfValues //calculates the product of an NSMutableArray of numbers
{
NSNumber *product=[NSNumber numberWithDouble:1.0];
for(int i = 0; i < [listOfValues count]; i++)
{
NSNumber *newVal = [listOfValues objectAtIndex:i];
product = [NSNumber numberWithDouble:[product doubleValue] * [newVal doubleValue]];
}
return product;
}
So, when I call these methods, I am getting the following error:
2013-08-04 13:52:04.514 effectCalculator[45573:c07] -[__NSArrayM doubleValue]:
unrecognized selector sent to instance 0x8c19e00
2013-08-04 13:52:04.521 effectCalculator[45573:c07] *** Terminating app due to uncaught
exception 'NSInvalidArgumentException', reason: '-[__NSArrayM doubleValue]: unrecognized
selector sent to instance 0x8c19e00'
Important to note: This error occurs on the retrieval, NOT the populating of the NSMutableDictionary. This means the population of this dictionary not the an issue, but it might have something to do with why it's having trouble retrieving the data.
So what might cause this error?
Your code is pretty difficult to follow. In future please post a minimal sample which compiles, or at least is a single block of understandable code.
Having said that, I believe your issue is with this bit:
for(id type in tEffect) //tEffect is the NSMutableDictionary, returned from the previous code (there known as resultDict)
{
effectivenessString = [self getEffectivenessString:[tEffect objectForKey:type]];
what does resultDict contain?
[resultDict setObject:dFactors ...
but dFactors is an NSMutableArray. Well getEffectivenessString expects a NSNumber, not a NSMutableArray. So it complains. Also I think you intended for the method to take a string, not a number, although I don't see why you're not casting as you load them (instead of as you use them).
Since Objective C doesn't support strongly-typed arrays or dictionaries, your best bet to defend against this in the future is to name your variables more logically. It should stand out when you try to call a method which expects a number with an array instead.
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];
I have this implementation file with aNSArray object userIDs
NSArray *userIDs;
NSInteger friendID;
#implementation TableViewController
-(void)reciveFriendsIDs:(NSArray *)array
{
userIDs = [NSArray arrayWithArray:array];
}
-(NSString *)getFriendId
{
return [userIDs objectAtIndex:friendID];
}
.
.
.
#end
and the method -(NSString *)getFriendId call it from another class like this :
TableViewController *tableController = [[TableViewController alloc]init];
NSString *fid = [tableController getFriendId];
But I am having an error said "-[__NSArrayI respondsToSelector:]: message sent to deallocated instance 0x20320200" and the compiler indicate the error in this line:
return [userIDs objectAtIndex:friendID];
You are allocating the NSArray with arrayWithArray static method.
In this way it's getting added in the auto release pool and the retain count will be 0.
Either retain it or manually alloc it with [[NSArray alloc] init]
I was getting the same exception on line
if(self.arrTypes != nil)
cause of the following line being used at a different place in code
[self.arrTypes release];
and replacing this code with
self.arrTypes = nil;
resolved the issue.
Well, I'm creating a custom SEL like:
NSArray *tableArray = [NSArray arrayWithObjects:#"aaa", #"bbb", nil];
for ( NSString *table in tableArray ){
SEL customSelector = NSSelectorFromString([NSString stringWithFormat:#"abcWith%#", table]);
[self performSelector:customSelector withObject:0];
}
I got a error:
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[Sync aaaWithaaa]: unrecognized selector sent to instance
but if i run it with the real method name it works!
[self performSelector:#selector(aaaWithaaa:) withObject:0];
How to solve it out?
You've already created selector from string - pass it to performSelector: method:
[self performSelector:customSelector withObject:0];
Edit: Mind, that if your method takes parameter then you must use colon when create selector from it:
// Note that you may need colon here:
[NSString stringWithFormat:#"abcWith%#:", table]
NSArray *tableArray = [NSArray arrayWithObjects:#"aaa", #"bbb", nil];
for ( NSString *table in tableArray ){
SEL customSelector = NSSelectorFromString([NSString stringWithFormat:#"abcWith%#:", table]);
[self performSelector:customSelector withObject:0];
}
- (id)performSelector:(SEL)aSelector withObject:(id)anObject
First argument is SEL type.
SEL customSelector = NSSelectorFromString([NSString stringWithFormat:#"abcWith%#", table]);
[self performSelector:customSelector withObject:0];
Close.
The difference is that with #selector(aaaWithaaa:) you pass a method name but with #selector(customSelector:) you're passing a variable of type SEL (with a spare colon).
Instead, you just need:
[self performSelector:customSelector withObject:0];
The other difference is that you write your string with a colon at the end, but you stringWithFormat: has none. It's important; it means that the method takes a parameter. If your method has a parameter, it needs to be there, i.e.,
[NSString stringWithFormat:#"abcWith%#:", table]
My init starts like this:
- (id) init {
[super init];
sounds = makeDictFromArrayOfURLs(getNoiseFileURLs());
[sounds retain];
NSURL *theFirstNoise = [[sounds allKeys] objectAtIndex:0];
CFURLRef uref = (CFURLRef)theFirstNoise;
OSStatus ret = AudioServicesCreateSystemSoundID(uref, &chosenNoise);
When we get to that last line, it throws this:
2011-06-09 23:19:18.744 SuperTimer[94516:207] -[NSPathStore2 _cfurl]: unrecognized selector sent to instance 0x940cfb0
2011-06-09 23:19:18.746 SuperTimer[94516:207] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[NSPathStore2 _cfurl]: unrecognized selector sent to instance 0x940cfb0'
Yeah, it's a bit uncompact for debugging.
Just before I get the dump, theFirstNoise contains the expected (sort of) data. (It's description method prints a weird form, but I am informed that's normal.)
Off the top of my head, it looks like theFirstNoise is actually an NSPathStore2 (a private subclass of NSString) instead of an NSURL.
Edit: NSPathStore2 objects will contain file paths. If you need to turn these into NSURLs, you can simply pass them to +[NSURL fileURLWithPath:].
This line:
NSURL *theFirstNoise = [[sounds allKeys] objectAtIndex:0];
is the problem: [sounds allKeys] returns an NSArray of keys, and objectAtIndex: therefore is returning an NSString, and not the URL. I wish the compiler would have been a little more helpful.