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;
Related
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 am trying to get index of an array through indexOfObject method as follows but when i try to log the value to test the index i get a garbage value.. for testing purposes i am having an array with values {57,56,58..} to get an index of lets say 56,
NSNumber *num = [NSNumber numberWithInteger:56];
NSInteger Aindex = [myArray indexOfObject:num];
NSLog(#" %d",Aindex);
the value i get is something like 2323421. what am i possibly doing wrong??
The index returned by indexOfObject will be the first index for an occurence of your object. Equality is tested using isEqual method.
The garbage value you get is probably equal to NSNotFound.
Try testing anIndex against it. The number you are looking for isn't probably in your array :
NSNumber *num=[NSNumber numberWithInteger:56];
NSInteger anIndex=[myArray indexOfObject:num];
if(NSNotFound == anIndex) {
NSLog(#"not found");
}
or log the content of the array to be sure :
NSLog(#"%#", myArray);
Folks,
When an object is not found in the array the indexOfObject method does NOT return a 'garbage' value. Many systems return an index of -1 if the item is not found.
However, on IOS - because the indexOfObject returns an UNSIGNED int (aka NSUInteger) the returned index must be greater than or equal to zero. Since 'zero' is a valid index there is no way to indicate to the caller that the object was not found -- except by returning an agreed upon constant value that we all can test upon. This constant agreed upon value is called NSNotFound.
The method:
- (NSUInteger)indexOfObject:(id)anObject;
will return NSNotFound if the object was not in the array. NSNotFound is a very large POSITIVE integer (usually 1 minus the maximum int on the platform).
NSNumber *num1 = [NSNumber numberWithInt:56];
NSNumber *num2 = [NSNumber numberWithInt:57];
NSNumber *num3 = [NSNumber numberWithInt:58];
NSMutableArray *myArray = [NSMutableArray arrayWithObjects:num1,num2,num3,nil];
NSNumber *num=[NSNumber numberWithInteger:58];
NSInteger Aindex=[myArray indexOfObject:num];
NSLog(#" %d",Aindex);
Its giving the correct output, may be u have done something wrong with storing objects in ur array.
Try this:
NSArray's indexOfObject: method. Such as the following:
NSUInteger fooIndex = [someArray indexOfObject: someObject];
If you're using Swift and optionals make sure they are unwrapped. You cannot search the index of objects that are optionals.
I just checked. Its working fine for me. Check if your array has the particular number. It will return such garbage values if element is not present.
indexOfObject methord will get the index of the corresponding string in that array if the string is like #"Test" and you find like #"TEST" Now this will retun an index like a long number
Am confused with the use of this method and the documentation that lists it as a (void) method.
"on return the index path's indexes"
where does it return anything too?
Should it not be:
- (NSIndexPath *)getIndexes:(NSUInteger *)indexes
getIndexes:
Provides a reference to the index path’s indexes.
- (void)getIndexes:(NSUInteger *)indexes
Parameters
indexes
Pointer to an unsigned integer array. On return, the index path’s indexes.
Availability
Available in iOS 2.0 and later.
Declared In
NSIndexPath.h
You have to allocate the NSUInteger array of size [indexPath length] and pass it as argument. The return value will be written there. You have to release that array yourself or do nothing it was created on stack like this:
NSUInteger array[[indexPath length]];
[indexPath getIndexes: array];
Maybe the next sentence explains the reason
It is the developer’s responsibility to allocate the memory for the C array.
It's actually a pointer to a C array that will be filled for you with the indexes, so there's no reason to additionally return it from the function - you already know its address.
You can use the function as follows
NSUInteger indexCount = [indices count];
NSUInteger buffer[indexCount];
[indices getIndexes:buffer maxCount:indexCount inIndexRange:nil];
You send that message to an instance of NSIndexPath, so getting one back wouldn't help. The -getIndexes: method fills the array 'indexes' with the indexes from the index path. So you'd do something like:
NSUInteger *indexes = calloc([indexPath length], sizeof(NSUInteger));
[indexPath getIndexes:indexes];
After that, indexes will be filled with the index values that are in indexPath.
Max, Thomas and Caleb, I have tried all three ways and cannot get anything to work, so maybe fired off the accepted solution too quick.....but probably more likely I just don't get it? I can't get the right size of the array in order to loop through it to access the required rows in my table. I would have though that calloc([indexPath length], sizeof(NSUInteger)) would for a group with 5 rows return an array with 5 rows with each row holding NSUIntegr.....or am of so far off beam it embarrassing?
why does '[self.pickerSubArray indexOfObject:self.txtSubCategory.text]' return '2147483647'; while the same string value argument '[self.pickerSubArray indexOfObject:#"Mark"]' brings up 4, as desired?
The Apple docs for NSArray (which I assume your object is, based on the name) say that indexOfObject: returns NSNotFound if the object does not match any in the array. NSNotFound is itself defined as NSIntegerMax which, as others have pointed out, is the value that you are getting back.
indexOfObject: uses isEqual: to compare the items, so in theory if the text is the same then it should be working. Perhaps the text is actually different in some way that you haven't noticed, such as case ("Mark" vs. "mark") or extra padding ("Mark" vs. "Mark ").
indexOfObject: returns NSNotFound if it can't find your exact object. NSNotFound is defined as NSIntegerMax, which is 2147483647.
Why is it doing that? I'm pretty sure indexOfObject: tests for an identical object, not an object with identical content.
e.g.
NSString *mark1 = [NSString stringWithString:#"Mark"];
NSString *mark2 = [NSString stringWithString:#"Mark"];
mark1 is not necissarily equal to mark2, because they're two different objects.
NSString *mark1 = [NSString stringWithObject:#"Mark"];
NSString *mark2 = mark1;
mark1 is equal to mark2;
BUT! Since the compiler is trying to minimize the memory footprint, it turns all literal strings in your code into one constant string. Which is why [[NSArray arrayWithObject:#"Mark"] indexOfObject:#"Mark"] works, but [[NSArray arrayWithObject:#"Mark"] indexOfObject:textField.text] doesn't work even if the text in textField.text is "Mark".
How do you fix it... well, indexOfObject: from the docs it looks like indexOfObject: is based on isEqual: so you should test if [self.txtSubCategory.text isEqual:#"Mark"]. to rule out the wrong value or a disconnected outlet, etc. After that, you may have to refactor to not use indexOfObject:
Just a guess about the number origin - it's a bad integer conversion. It was very probably meant to return -1.
That kindof leads me to believe that you might have found some badness in underlying libraries/languages.
NSDecimalNumber *lat = [[NSDecimalNumber alloc]initWithDouble:sqlite3_column_double(selectStatement, 1)];
[latt addObject:lat];
[lat release];
CLLocationCoordinate2D annot;
annot.latitude = [[latt objectAtIndex:k]doubleValue];
The above 2 codes shows the creation and retrieving of double values from an array. I've stored some values of type double in the database. I retrieve them and store them in an array. I'm not getting any problem there.
But when i try to get them out of the array, as in the second one, i'm getting a warning, paasing argument 1 if 'objectAtIndex' makes pointer from integer without a cast. What might be the problem?
Also when i try to assign the unsigned integer stored in the array as NSNumber to an unsigned integer variable, 'm getting a warning assignmentmakes pointer from integer without a cast. What are these warnings pointing to?
[back addObject:[NSNumber numberWithUnsignedInt:12]];
k = [[back objectAtIndex:0]unsignedIntegerValue];
Define k as an NSUInteger:
NSUInteger k;