indexOfObjectIdenticalTo: - Getting junk value - objective-c

NSString *yes0 = #"yes";
NSString *yes1 = #"YES";
NSString *yes2 = #"Yes";
NSString *yes3 = [NSString stringWithFormat:#"%#",yes1];
NSArray *yesArray = [NSArray arrayWithObjects:#"yes", #"YES", #"Yes", #"YES", nil];
NSArray *yesArray1 = [NSArray arrayWithObjects:yes0, yes1, yes2, yes3, nil];
NSUInteger index;
index = [yesArray indexOfObjectIdenticalTo:yes3];
NSLog(#"\nindex : %d", index); // 1st Output
index = [yesArray1 indexOfObjectIdenticalTo:yes3];
NSLog(#"\nindex : %d", index); // 2nd Output
1st Output
Output i receive is: "2013-07-18 16:42:04.896 Collections - Arrays[2778:f803] index : 2147483647"
2nd Output
Output i receive is: "2013-07-18 16:42:04.896 Collections - Arrays[2778:f803] index : 3"
I get confused due to the outputs i receive. Kindly explain me the process why i get the junk value during the output 1. According me, both arrays are identical with objects. Then why this junk value.
Also having a question:
According to apple, indexOfObjectIdenticalTo: returns - The lowest
index whose corresponding array value is identical to anObject.
Upto my understanding, in yesArray1 - yes1 is same as yes3. My expecting value of output 2 is 1 which gets contradict with the actual printed value (3). Also please let me understand it properly why it is printing 3 rather than 1.

First off, it's not a "junk value", it's the NSNotFound constant.
The first index is not found because yes3 is not in yesArray (it's only in yesArray1) – note that indexOfObjectIdenticalTo: checks for pointer identity, not object equality (unlike indexOfObject:).

indexOfObjectIdenticalTo checks for pointer equality, not object equality. 2147483647 isn't a junk value, it's the value of NSNotFound (which is the defined result if no index is found).

indexOfObjectIdenticalTo : checks for pointer equality
indexOfObject: checks Object equality.
Good Luck !!!

Related

is NSDictionary non-ordered completely

As we know,NSDictionary is non-ordered.however,when keys is number,when the dictionary is printed,they are printed by ascending number. i have try many times.
the order of a dictionary depends on the value that is returned by the hash method of the added key-object. it is very like, that NSNumber returns its value, it is was created with an Integer. in that case your observation would be correct.
more infos: http://bynomial.com/blog/?p=73
try ing this code
NSArray *numbers = #[#0,#1,#2,#3];
for (NSNumber *n in numbers) {
NSLog(#"%ld:%#", (unsigned long)[n hash], n);
}
it produces this output
0:0
2654435761:1
5308871522:2
7963307283:3
seems as if Knuth's hash algorithm was implemented half.
The original is
hash(i)=i*2654435761 mod 2^32
here it seems to be just
hash(i)=i*2654435761

NSNumber returning different value than the original int

I am quite new to objective-c and I am trying to convert an int into a NSNumber so that I can save it into Core-Data.
I've the following piece of code (index is an NSInteger)
- (void) associateOrNotToARoutine:(NSString*)exerciseName associate:(BOOL)associate index:(NSInteger)index
NSLog(#"number w index %d, %d",[NSNumber numberWithInteger:index],index);
and it returns
number w index 170413600, 2
I need an int of 2 to be translated into a number 2 along with all other numbers to be translated into the correct number... Could anyone tell me why i am getting this convertion? I tried reading on NSNumber manual but i found nothing
Try:
NSLog(#"number w index %#, %d",[NSNumber numberWithInteger:index],index);
^^
The %# format specifier will call the [NSNumber description] method, which should return the value you are after. Your original code will return the address of the NSNumber object, not its content.
Even though this question has already been answered, I thought I'd flesh out a longer answer for future readers in general:
What's happening?
%d is a C format string used to indicate one of the passed parameters is an integer (int) ivar value. Much like %f is used for float values.
[NSNumber numberWithInteger:index] returns a pointer to an NSNumber instance. If you use %d, NSLog thinks you're passing it an integer when, in fact, you're passing a pointer. So the pointer value (a memory address) is printed.
What's %#?
As mentioned by trojanfoe: %# tells NSLog() that you are passing an object. In that case, NSLog asks the object to describe itself using a string… it calls the description method.
Specific answer
For this specific question, there are multiple ways. The two main one being:
NSLog(#"number w index %#, %d", [NSNumber numberWithInteger:index], index);
NSLog(#"number w index %d, %d", [[NSNumber numberWithInteger:index] intValue], index);
Extra goodness
When using %#, the passed object can be anything that responds to description, essentially any descendant of NSObject. Also, if you're creating your own classes, it's a good idea to overload description to return a more meaningful string than the default NSObject implementation.
// Try using it with NSArray or NSDictionary and see how each describe themselves.
NSLog(#"the array description: %#", myArray);
NSLog(#"the dictionary description: %#", myDictionary);
You should use,
[[NSNumber numberWithInteger:index] intValue]
to get the integer value, the NSNumber, is holding

arc4random in NSNumber giving negative values?

I'm creating a random number and storing it in a NSNumber object like this:
NSNumber *index = [NSNumber numberWithUnsignedInt:arc4random_uniform(2^32-1)];
I also tried:
NSNumber *index = [NSNumber numberWithUnsignedInt:arc4random_uniform(4294967295)];
NSNumber *index = #(arc4random_uniform(4294967295));
At some point I'm also assigning the number 1 like this:
NSNumber *index = #(1);
This should give me only positive numbers.
Later on, I print out these numbers like this:
NSString *string = [NSString stringWithFormat:#"%#", index];
This gives me some negative values for the random numbers and 1 is being printed as 1. So I though maybe if I do:
NSString *string = [NSString stringWithFormat:#"%u", index.unsignedIntValue];
I'll get only positive numbers - which I do - but now 1 is suddenly being printed as some large positive number, also.
What's going on here? How can I correctly store a u_int32 (which arc4random returns) in a NSNmber and make sure that they are only positive?
Use
NSNumber *index = [NSNumber numberWithUnsignedInt:arc4random_uniform(exp2(32)-1)];
I never get any negative numbers. arc4random_uniform(x) always returns a number between 0 and x, and the stringvalue of the NSNumber generated from it is correct.
EDIT: replaced exp2(31) with exp2(32)
You said in a comment that the index is stored in a Core Data entity as an "Integer 32" attribute, and I assume that is where the problem comes from.
Core Data dynamically generates getter and setter methods for all attributes (and relationships) of managed object classes. These accessor methods are different from the "usual" #synthesized accessor methods which are backed up by an instance variable.
For an "Integer 32" attribute, Core Data uses a (signed) integer for the attribute, and when you set a value, it is just cast or truncated to int. Example:
e.index = [NSNumber numberWithUnsignedInt:0xFFFFFFF0U];
// This would give the same result:
// e.index = [NSNumber numberWithLongLong:0x1234FFFFFFF0LL];
NSNumber *val = e.index;
NSLog(#"value=%#, type=%s", val, [val objCType]);
// Output: value=-16, type=i
The output type=i shows that the value contains an int.
If you need unsigned integers in the range 0 .. 2^32-1, then you can either (as you already did) use unsignedIntValue:
unsigned x = [val unsignedIntValue];
or store the attribute as "Integer 64".
Remarks:
I am fairly sure that this is not a problem of arc4random_uniform.
In your first code example arc4random_uniform(2^32-1), you should note that ^ is exclusive-or, not exponentiation.

Get NSArray index number

self.listData = [NSArray arrayWithObjects:#"A",#"B",#"C", nil];
How can I get index numbers for listData items?
This code below is used to get listData items string:
c = [NSString stringWithFormat:#"%#",[listData objectAtIndex:indexPath.row];
Any idea?
Thanks
Something like...
NSUInteger index = [listData indexOfObject:#"A"];
From the docs:
Return Value
The lowest index whose
corresponding array value is equal to
anObject. If none of the objects in
the array is equal to anObject,
returns NSNotFound.
Discussion
Objects are considered
equal if isEqual: returns YES.
** Important: If anObject is nil an exception is raised.**
If you can guarantee that the strings in your array are unique, then using indexOfObject: will work. Otherwise, you'll need to use one of the indexesOfObjects* methods such as indexesOfObjectsWithOptions:passingTest: to get a set of all of the indexes containing the object you're interested in.

Different behavior - NSDictionary on iPad vs. iOS Simulator

int a = 0;
NSDictionary* d = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithInt:a], #"A",
[NSNumber numberWithInt:a+=1], #"B",
[NSNumber numberWithInt:a+=1], #"C",
nil];
NSLog(#"%#", d);
Result on iPad:
{
A = 0;
B = 1;
C = 2;
}
Result in iOS Simulator:
{
A = 2;
B = 2;
C = 1;
}
Can anyone reproduce the result, or even better, explain it?
This is undefined behavior. There is no right answer for those values. The order in which effects are applied is undefined between sequence points, and the commas in an argument list are not sequence points.
The order of evaluation of arguments to a function or method is undefined and determined by the compiler. This means that there is no guarantee that the first number will be created before the second, and is inherited by objective-c from c. It appears that on the iPad, they are being executed in the same order that they are in the code, but for the simulator they are created in reverse order. This is the order of events:
iPad:
Evaluate first argument. This is a method. Its arguments must be processed:
The argument is the variable a. Use its current value (0).
Evaluate second argument. This is a constant string. Load its address.
Evaluate third argument. This is a method. Its arguments must be processed:
The argument is an expression: a += 1. Increment a and return its new value (1).
Evaluate fourth argument. This is a constant string. Load its address.
Evaluate fifth argument. This is a method. Its arguments must be processed:
The argument is an expression: a += 1. Increment a and return its new value (2).
Evaluate sixth argument. This is a constant string. Load its address.
Simulator:
Evaluate sixth argument. This is a constant string. Load its address.
Evaluate fifth argument. This is a method. Its arguments must be processed:
The argument is an expression: a += 1. Increment a and return its new value (1).
Evaluate fourth argument. This is a constant string. Load its address.
Evaluate third argument. This is a method. Its arguments must be processed:
The argument is an expression: a += 1. Increment a and return its new value (2).
Evaluate second argument. This is a constant string. Load its address.
Evaluate first argument. This is a method. Its arguments must be processed:
The argument is the variable a. Use its current value (2).
Since the calling convention of i386, which is used by the simulator, is that arguments are passed on the stack in reverse order, I would guess that this is why the compiler evaluates them in reverse order.
To fix your problems, you should create the NSNumber objects before creating the dictionary, forcing the compiler to use the order you want.
int a = 0;
NSNumber *numA = [[NSNumber alloc] initWithInt:a];
a += 1;
NSNumber *numB = [[NSNumber alloc] initWithInt:a];
a += 1;
NSNumber *numC = [[NSNumber alloc] initWithInt:a];
NSDictionary *d = [NSDictionary dictionaryWithObjectsAndKeys:numA, #"A", numB ,#"B", numC, #"C", nil];
[numA release];
[numB release];
[numC release];
NSLog(#"%#", d);