I made a request to facebook API using facebook SDK to get user basic data. Everything works ok, but when I try to pass the facebook ID as a NSInteger number the returned number is wrong.
The facebook ID is: 100001778401161
But after convert the number to NSInteger the number returned is: 2054848393
How can I store the facebook ID on a NSInteger variable?
My current code is:
NSLog(#"The ID: %ld", (long)[[user objectForKey:#"id"] intValue])
Thanks.
Such a number needs 64 bits, NSInteger does only cover 32 bits (and with positive numbers only 31 bits). Try using long long values:
NSLog(#"The ID: %lld", [[user objectForKey:#"id"] longLongValue]);
you can use also NSNumber if you need to store it as an object somehow:
NSNumber *number=[NSNumber numberWithLongLong:[user[#"id"] longLongValue]];
NSInteger (and long) is a 32-bit value and the ID you are using exceeds the maximum value that it can hold, so it overflows. You could try:
long long facebookId = [[user objectForKey: #"id"] longLongValue];
NSLog(#"The ID: %lld", facebookId);
I don't know anything about the facebook API so you might want to make sure that the ID is guaranteed to be numeric over time. If, for example, they specify somewhere that the ID is a string, you should match that even if they seem to always be numeric.
You can't store the number larger than 2 ^ 31 in NSInteger type.
If you want to store the one larger, then you can use NSDecimalNumber object instead.
Or you can use unsigned long long type.
NSDecimalNumber *number = [NSDecimalNumber decimalNumberWithString:[user objectForKey:#"id"]];
NSLog(#"Number: %#", number);
unsigned long long ullValue = strtoull([user objectForKey:#"id"], NULL, 0);
NSLog(#"Number: %llu", ullValue);
Hope this will help you!
Related
I have an array with 10 items. When I call "IndexOfObject" for the elements number 9 and the element number 10 Xcode return an exception: "NSRangeException"
reason: '_[_NSCFArray objectAtIndex:] index:2147483647 beyond
bounds(10)'.
From a previous NSLog, I saw that the two elements exist in the array but indexOfObject not find them. Why?
My code is:
NSDictionary * headConfig =[avatarDictionaryToSave objectForKey:#"head_dictionary"];
NSString * headImage =[headConfig objectForKey:#"layer_key"];
NSString * pathFace =[[NSBundle mainBundle]pathForResource:#"Face" ofType:#"plist"];
NSLog(#"%#", headImage);
NSArray *arrayFace =[NSArray arrayWithContentsOfFile:pathFace];
NSLog(#"the elements are: %#", arrayFace);//here headImage is present
int index =[arrayFace indexOfObject:headImage];
NSLog(#"the index is %d", index);
indexOfObject: returns NSNotFound when the object is not present in the array. NSNotFound is defined as NSIntegerMax (== 2147483647 on iOS 32 bit).
So it seems that the object you are looking for is just not there.
Please change the coding of adding the array values as I mentioned below.
// [arr_values addObject:[dictionary valueForKey:#"Name"]];
[arr_values addObject:[NSString stringWithFormat:#"%#",[dictionary valueForKey:#"Name"]]];
When target array elements are not in string format then while we using the
indexOfObject then that value can't able to find in the target array. So please try to
change the value of object as mentioned above while adding into array.
By default, an integer is assumed to be signed.
In other words the compiler assumes that an integer variable will be called upon to store either a negative or positive number. This limits the extent that the range can reach in either direction.
For example, a 32-bit int has a range of 4,294,967,295. In practice, because the value could be positive or negative the range is actually −2,147,483,648 to +2,147,483,647.
If we know that a variable will never be called upon to store a negative value, we can declare it as unsigned, thereby extending the (positive) range to 0 to +4,294,967,295.
An unsigned int is specified as follows:
unsigned int myint;
Something weird just happened.
I stored a NSNumber with an unsigned long long value in NSUserDefaults. When I retrieve it, the value just changed. It seems that system thinks the number is long long instead of unsigned long long.
What's worse is that when I compare the number retrieved from UserDefaults with the original number, the result is NotEqual!
what's wrong with the code? Thank you!
static NSString * const NumberKey = #"MyNumber";
unsigned long long value = 15908045869032883218ULL;
if ([[NSUserDefaults standardUserDefaults] objectForKey:NumberKey] == nil) {
NSNumber *number = [NSNumber numberWithUnsignedLongLong:value];
[[NSUserDefaults standardUserDefaults] setObject:number forKey:NumberKey];
NSLog(#"Original Number:%#", number); // 15908045869032883218, right
}
NSNumber *number = [[NSUserDefaults standardUserDefaults] objectForKey:NumberKey];
NSLog(#"Current Number:%#", number); // -2538698204676668398, weird
NSLog(#"Current Value:%llu", [number unsignedLongLongValue]); // 15908045869032883218, right
NSLog(#"%d", [number isEqualToNumber:[NSNumber numberWithUnsignedLongLong:value]]); // 0
NSLog(#"%d", [number unsignedLongLongValue] == value); // 1
To further answer your question. If you look in the documentation for NSNumber's isEqualToNumber: function you will notice the following line,
Two NSNumber objects are considered equal if they have the same id values or if they have equivalent values
it's important you understand this. In your code you are asking is my NSNumber object "number" equal to "value", you are not asking does the numerical value stored within my NSNumber object "number" equal the numerical value stored within my NSNumber object "value".
The last line of code you have written shows that in fact your NSNumber's numerical values are in fact equal.
NSLog(#"%d", [number unsignedLongLongValue] == value); //1
So you are correctly storing and retrieving the values, you should be using the == comparison method with NSNumber objects stored numerical values (ie intValue == intValue, unsignedLongLongValue == unsignedLongLongValue) and not comparing their object id's together.
As for this line of code
NSLog(#"Current Number:%#", number); // -2538698204676668398, weird
This is not weird, this is perfectly normal, as you have told NSLog to print out an NSObject representation of 'number'. I'm not 100% certain but I believe that NSNumber's - ( NSString * ) description function defaults to return an unsigned int value for the numerical value it contains. This is why you are getting the large negative number returned. You may want to look at NSNumber's - (NSString *)descriptionWithLocale:(id)aLocale function to print out the data in a more logical for for you, or you could use
NSLog(#"Current Number:%llu", [number unsignedLongLongValue]);
Which will give you the right answer.
EDIT:
Further to this, after looking into the issue what is happening is that on recollection of your NSNumber object from UserDefaults it's original number type is not being preserved (this information is highlighted in the documentation for NSNumber in the overview section)
(Note that number objects do not necessarily preserve the type they are created with.)
You can see this yourself if you log the following after retrieving "number" from user defaults (add this to the end of the code you have in your question) and have a look at the encoding values shown here
NSLog(#"%s", [number objCType]); //This will log out q
NSLog(#"%s", [[NSNumber numberWithUnsignedLongLong:value] objCType]); //this will log out Q
The difference between Q and q is that Q is an unsigned value... hence why you are having issues with the isEqualToNumber: function as the number types are different.
If you are so dead set on using the iSEqualToNumber: function to compare values then you could implement this to retrieve your value from NSUserDefaults.
NSNumber *number = [NSNumber numberWithUnsignedLongLong:[[NSUserDefaults standardUserDefaults] objectForKey:NumberKey] unsignedLongLongValue]];
You could look at using the NSNumber compare: function to see if the returned value is NSOrderedSame however this will not work for comparing unsigned vs signed values of the same type so in your situation I'd use the above as retrieving the data from NSUserDefaults is stripping the "signedness" of your number.
At the end of the day if you want to store NSNumber into NSUserDefaults this code works for me even for large integers like: 881217446193276338
To save:
[[NSUserDefaults standardUserDefaults] setObject:self.myUser.sessionid forKey:#"sessionid"];
[[NSUserDefaults standardUserDefaults] synchronize];
To recover:
self.myUser.sessionid = (NSNumber *)[[NSUserDefaults standardUserDefaults] objectForKey:#"sessionid"];
It's storing it correctly, nothing is wrong with your code except:
NSLog(#"Current Number:%#", number);
Here number is a non-string object, you might think of it as a wrapper for a numerical primitive. Or you might think that NSNumber instances objectify a primitive type.
What you need is some thing like:
NSLog(#"Current Number:%#", [number stringValue]);
Here is a speculative answer:
The NSNumber documentation states that:
(Note that number objects do not necessarily preserve the type they are created with.) .
So it must be using a different internal storage for this type, and only gives you the correct value when you specifically ask for the unsigned long long value. The description method, which is called in your NSLog statement, may be defaulting to a different representation type.
And / or there may be some quirk of the unarchiver that is preventing the isEqualToNumber method working on the value returned from defaults. If you do that comparison between two NSNumbers created in the same scope, does it work? The correct value is definitely in there somewhere given your last statement returns true.
I'm trying to convert an NSString object to an NSNumber with the same numerical value. When I create the NSString object using this statement...
NSString *songID = [localNotif.userInfo objectForKey:#"SongID"];
the var songID contains the string value #"10359537395704663785". and when I attempt to convert it to an NSNumber object using the statement...
NSNumber *songIDNumber = [NSNumber numberWithLongLong:[songID longLongValue]];
the var songIDNumber contains the wrong value of 9223372036854775807
What am I doing wrong? It might also be worth noting that sometimes this code does work and produce the correct NSNumber value, but most of the time it fails as shown above.
Thanks in advance for your help!
UPDATE: God I love this site! Thanks to unbeli and carl, I was able to fix it using the updated code for converting from the NSString to the NSNumber...
unsigned long long ullvalue = strtoull([songID UTF8String], NULL, 0);
NSNumber *songIDNumber = [NSNumber numberWithUnsignedLongLong:ullvalue];
longLongValue returns LLONG_MAX in case of overflow, and LLONG_MAX is exactly what you get, 9223372036854775807. You value simply does not fit in long long
Try using NSDecimalNumber instead.
9223372036854775807 decimal is 0x7FFFFFFFFFFFFFFF in hex. Your number is 10359537395704663785, which is too large for a long long and overflows. From the NSString documentation:
Returns LLONG_MAX or LLONG_MIN on overflow.
I want to get the unsigned long value of a NSNumber. I don´t know why, but it doesn't work. Here is what I did:
NSString * stern = [idd objectAtIndex:indexPath.row]; // get a String with Number from a NSArray
NSNumberFormatter * lols = [[NSNumberFormatter alloc] init];
NSNumber * iddd = [lols numberFromString:stern];
NSLog(#"%#", iddd); // I get the right number: 8084143463
unsigned long fooo = [iddd unsignedLongValue];
NSLog(#"%lu", fooo); // I get the wrong number: 3789176167
[twitterEngine deleteUpdate:fooo];
8084143463 == 0x1e1da3d67
3789176167 == 0x0e1da3d67
The size of a long on a 64bit system is 8 bytes. The size of a long on a 32bit system (like the iPhone) is 4 bytes. You need to use a long long on an iPhone to store that value.
Your value is larger than the maximum value an unsigned long can hold (2^32 - 1 == 4,294,967,295) in 32-bit mode.
I've got an NSDictionary that was initialized with a plist that, among other things, contained count followed by 32 and I want to get at the value for count.
How?
I know how to get it into an object via
[dictionaryObjectName objectForKey:#"count"]
But to me, the value I'm obtaining is not an object.
If I have to specify an object, what would be the best one to use (FYI the value will always be unsigned) and I need to get it into a true int.
Do I do something like
NSNumber *num = [dictionaryObjectName objectForKey:#"count"];
int theValue = [num intValue];
[num release];
Is the release on num a good thing to do since this for an iPhone with no garbage collector?
And nicer form is:
int theValue = [[dictionaryObjectName objectForKey:#"count"] intValue];
EDIT
Since I see that people still arrive to this page, let's clarify that these days you simply do
int theValue = [dictionaryObjectName[#"count"] intValue];
Yes, you pull it out as an NSNumber, then grab the int(eger)Value but there's no need to release it. You didn't retain, alloc, or copy the number, so you don't have to worry about releasing it.