I am getting this error:
'-[ProductionCellData objectForKey:]: unrecognized selector sent to instance 0x14dca5d0'
on this line of code:
NSString *productionItem = [[myArray objectAtIndex:keyCounter] objectForKey:#"baseLineStart"];
keyCounter is equal to 0 and here is what myArray looks like
I am trying to get the value of baseLineStart but I keep getting the error above....how do I fix this?
objectForKey is normally used in dictionaries.
If you want to access the property, just refer to it:
NSString *productionItem = [myArray objectAtIndex:keyCounter].baseLineStart;
Or with even more modern syntax:
NSString *productionItem = myArray[keyCounter].baseLineStart;
The fact is that ProductionCellData does note responds to this selector, you should use
- (nullable id)valueForKey:(NSString *)key;
or get property from object in this way (if it is public )
NSString *productionItem = [[myArray objectAtIndex:keyCounter] baseLineStart];
Try to find error by the following way.
NSDictionary *dic = [myArray objectAtIndex:keyCounter];
NSLog(#"dic:%#",dic);
NSString *productionItem = [dic objectForKey:#"baseLineStart"];
//1. observe the dic object has "baseLineStart" key. if not found write the correct one.
//2. objeserve what type of value returns "[myArray objectAtIndex:keyCounter]". it may not NSDictionary which may resoan of crash
Related
I develop in objective-c for a couple years now, but never faced something like this. I'd like to know if someone have an explanation why this is possible, look:
NSNumber *number = [NSNumber numberWithDouble:1.23413];
NSDictionary *dicTest = #{ #"number": number };
NSString *string = [dicTest valueForKey:#"number"];
NSLog(#"Is string? %d", [string isKindOfClass:[NSString class]]);
NSLog(#"Is number? %d", [string isKindOfClass:[NSNumber class]]);
The debugger says that the type of the variable is:
string __NSCFNumber * (double)1.23413 0x000060c000222ae0
How this is possible at runtime without crashing? Objective C isn't suposed to be typed?
Objective-C doesn't strongly enforce types in the way you expect.
The return type of valueForKey: is id, which means “object identifier”. The id type can reference an instance of any class and can be converted to a pointer to any specific class without any checking. You won't get an error unless you send an unrecognized message to the instance. For example, this statement:
NSLog(#"length = %ld", (long)string.length);
triggers this run-time error:
-[__NSCFNumber length]: unrecognized selector sent to instance 0x100404230
You can enforce stronger typing sometimes using “lightweight generics”. However, you first need to understand that you should not generally be using valueForKey:. The valueForKey: message is part of “key-value coding” (KVC) and is a way to access an object's properties by name at runtime. You should instead use objectForKey: on a dictionary ([dicTest objectForKey:#"number"]) or just use subscripting directly (dicTest[#"number"]).
Okay, so let's say you mend your ways and use objectForKey instead. Then, if all the values in the dictionary will be NSNumber *, you can declare your dictionary like this:
NSDictionary<NSString *, NSNumber *> *dicTest = #{ #"number": number };
Then you'll get a warning if you assume a different type for a value extracted from the dictionary:
NSString *string = [dicTest objectForKey:#"number"];
// warning: incompatible pointer types initializing 'NSString *' with an expression of type 'NSNumber * _Nullable' [-Wincompatible-pointer-types]
NSString *string = [dicTest valueForKey:#"number"];
You're essentially "casting" the result of the dictionary lookup to be an NSString. There's no check that the result of the dictionary lookup is actually an NSString.
string __NSCFNumber * (double)1.23413 0x000060c000222ae0
The debugger shows that your variable string is actually an NSNumber, not an NSString.
How this is possible at runtime without crashing?
There's nothing illegal about declaring a an object as a completely unrelated Type. You only run into trouble when you send an invalid message that the object is unable to interpret.
For example both NSNumber and NSString have the property boolValue.
#property(readonly) BOOL boolValue;
So if you send boolValue to your "NSString", the true NSNumber object will still respond to that message. No Exception.
But if you use a String-specific method/property that ONLY NSString implements, the true NSNumber object will not be able to respond. This causes the Exception.
Hi I am getting this data form server
NSDictionary*feed=[saveDic objectForKey:#"feed"];
NSLog(#"%#",feed); //Outputs: feed = ( { code = yQ7j0t; "user_id" = 889445341091863; } ); }
NSLog(#"%#",[feed valueForKey:#"code"]);
NSString *referralCode = [feed valueForKey:#"code"];
NSLog(#"%#",referralCode);
self.referralCode.text=referralCode;
And beacuse of that I am getting below error.
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSArrayI length]: selector sent to instance 0x165d5150'``
Any help will be appreciated.
The issue is, your feed key holds an array. You are not properly handling that in your code, that is why the crash occurs. When you call valueForKey: it retrieves an array of values held by that specific key.
For fixing that you can use:
NSArray *feed = [saveDic objectForKey:#"feed"];
NSArray *referralCodes = [feed valueForKey:#"code"];
NSString *referralCode = referralCodes.count ? referralCodes[0] : #"";
NSLog(#"%#",referralCode);
But I personally prefer using objectForKey: instead of valueForKey:. So you can re-write the code like:
NSArray *feed = [saveDic objectForKey:#"feed"];
NSString *referralCode = feed.count ? [feed[0] objectForKey:#"code"] : #"";
NSLog(#"%#",referralCode);
Some where you use a variable;
yourVaribleName.length
or
[yourVaribleName length]
which should be
yourVaribleName.count
note: the crash says exactly that "yourVaribleName" is NSArray type where you wants length of the NSArray. But NSArray has not feature "length". NSArray has "Count" feature
//try with this code bellow
NSArray *referralCode = [feed valueForKey:#"code"];
NSLog(#"%#",referralCode);
self.referralCode.text=[referralCode componentsJoinedByString:#" "];//#"," or #"" what event you need
Your feed data is in array. So you have retrieve code value from array.Hope it will help you.
NSMutableArray*feed=[saveDic objectForKey:#"feed"];
NSLog(#"%#",feed);
NSLog(#"%#",[feed valueForKey:#"code"]);
NSString *referralCode = [[feed objectAtIndex:indexPath]valueForKey:#"code"];
NSLog(#"%#",referralCode);
self.referralCode.text=referralCode;
Looking this [__NSArrayI allKeys]: unrecognized selector sent to instance error up, it seemingly occurs when you send an NSArray the allKeys message which is meant for NSDictionary, but in this case I'm very clearly sending it to an NSDictionary.
Here's the code I use when interfacing with the Pocket API:
NSDictionary *articles = [response objectForKey:#"list"];
// Create an array we can use to sort the keys (and thus the articles) in order of when they were added
NSMutableArray *allKeys = [[articles allKeys] mutableCopy];
The last line there causes the error. But articles is very clearly declared as an NSDictionary? Why is it not liking it?
Oddly enough, if I inspect it at runtime it says it's an NSArray! Why did it change?
(lldb) po articles
$5 = 0x082103e0 <__NSArrayI 0x82103e0>(
)
(lldb) po [articles class]
$6 = 0x01b83b8c __NSArrayI
(lldb)
It may be declared in your code as a dictionary, but that doesn't make it a dictionary. It is truly an array and that is why you get the exception. Check your response so you know what you should expect.
Your code compiles because the compiler doesn't know that it's going to be an array and it trusts you that it will be a dictionary. It does this because objectForKey: returns id.
I take datas from server. My app work fine in Sinulator and test device iPhone 4s, but one man have problem on iPod 4. He get exception:
-[__NSCFString objectForKeyedSubscript:]: unrecognized selector sent to instance 0x1d263a20
I cann't use this device so I write code to know where crash was.
if (![dictionaryRest[#"compliments"] isEqual:[NSNull null]]) {
NSMutableArray *array = [NSMutableArray new];
NSMutableArray *firstArray = [NSMutableArray new];
for (NSDictionary *dic in dictionaryRest[#"compliments"]) {
Compliment *compl = [Compliment new];
if (![dic[#"ID_promotions"] isEqual:[NSNull null]])
compl.ID = [dic[#"ID_promotions"] integerValue];
So in last 2 strings this exception was. What the reason of this? So I understand that I need use
if ([dict objectForKey:[#"compliments"])
instead
if (![dict[#"compliments"] isEqual:[NSNull null]])
and in all another cases.
I test now and I have in my dictionary for ID:
You have an NSString instance in your dictionary where you expect a dictionary.
Note that your "use this instead of that" has nothing to do with the problem.
-objectForKeyedSubscript: is an instance method on NSDictionary object.
__NSCFString objectForKeyedSubscript: exception indicates that the method -objectForKeyedSubscript is somehow getting called on some NSString object.
So basically you just have to properly check for the class of the object before you can safely assume that it is actually dictionary.
if([dic isKindOfClass:[NSDictionary class]])
{
id obj = dic[#"key"];
}
In iOS 6 I can do this:
NSDictionary *d = #{anObject : "key"};
But apparently when the object is a UIImageView or UIWebView (or maybe others too), it crashes with:
'NSInvalidArgumentException', reason: '-[UIWebView copyWithZone:]: unrecognized selector sent
Changing the dictionary declaration to the old way works:
NSDictionary *d = [NSDictionary dictionaryWithObjectsAndKeys:anObject,#"key", nil];
Any idea why this happens?
The syntax is
NSDictionary *d = #{<key> : <value>, ...};
In your case:
NSDictionary *d = #{#"key" : anObject};
So your code tried to use anObject as the key. That failed for UIWebView because keys must
conform to the NSCopying protocol .
This is because the new syntax expects keys and values to be ordered in reverse, compared to dictionaryWithObjectsAndKeys:
NSDictionary *d = #{ #"key" : anObject};
Also, do not forget the # sign in front of NSString literal.
Key first, value second.
NSDictionary *d = #{#"key" : nObject};