2
votes

I have a NSDictionary object get from server API. data is like this,

"filesize_mp3":"60488"

when I use following code to retrieve file size, app crashes. obj.filesize is in long type.

obj.filesize = [[dict objectForKey:@"filesize_mp3"] longValue],

lldb console,

2014-07-22 12:50:14.643 YouVoiceNews[2019:60b] -[__NSCFString longValue]: unrecognized selector sent to instance 0x9bf8e10
2014-07-22 12:50:14.644 YouVoiceNews[2019:60b] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFString longValue]: unrecognized selector sent to instance 0x9bf8e10'

but when I use

obj.filesize = (long)[dict objectForKey:@"filesize_mp3"]; 

everything is fine.

so my question is what's the differences between above 2 ways. why first one cause app crash?

Thanks in advance.

1
Read the error. NSString doesn't have a method named longValue. See the docs for NSString.rmaddy
one doesn't work with warning and one doesn't work without warning.Bryan Chen
Your second line of code does not do what you think it does. It is completely wrong despite the lack of a crash.rmaddy
Thanks a lot. Xcode's intelligent sense shows a longValue method. I should pay more attention on doc. change to longLongValue or integerValue is fine.LetBulletFlies

1 Answers

7
votes

Answer to question 1: what's the differences between above 2 ways?

  1. The first approach attempts to send the message -longValue to the object stored at key @"filesize_mp3"
  2. The second approach attempts to cast the pointer to the object stored at key @"filesize_mp3"

Answer to question 2: why does the first one cause the app to crash?

  1. The object stored at key @"filesize_mp3" is a NSString, and -longValue is an invalid selector. The reason the code compiled in the first place is because [dict objectForKey:@"filesize_mp3"] is not typed (it's an id), and for convenience id will accept any selector at compilation time. A slightly more conservative approach is provided below ; casting the object to a NSString will not allow [filesizeStr longValue].
  2. The second approach does not crash because you are simply casting a pointer into a long. While it does not give you anything of interest, it is a valid operation.

Answer to the question you did not ask: What should I have done?

Your dictionary contains NSString, not NSNumber nor int or long. A dictionary is a collection ofNSObject. Thus you must convert these strings into int, long or whatever format you see fit.

NSString * filesizeStr = [dict objectForKey:@"filesize_mp3"];
obj.filesize = [filesizeStr longLongValue];