different values for NSNumber long in Objective-C - objective-c

I have a variable which is a NSNumber of type long. It should hold the value -1.
When I log it to the Console it shows the expected value -1.
NSLog(#"myVariable %#", self.myVariable);
But the following expression in the if-clause is false.
if (myVariable == [NSNumber numberWithInt:-1]) {
...
}
The debugger shows the value 72057594037927935. Does anybody know what's wrong with it?
Thanks!

When you compare NSNumber to other objects, you have two options that do different things:
You can use == to check if two objects represent the same exact object instance, or
You can use isEqual: method to check if two objects represent the same value.
In your case the safest approach would be to use the second alternative
if ([myVariable isEqual:[NSNumber numberWithLong:-1]]) {
...
}
The == approach may or may not work, depending on the way in which you produced myVariable.

NSObject has a method: (NSString *)description
This method will define which is printed out when you put object on NSLog method.
NSNumber inherits NSObject and description method is implemented in the way that primitive value will be printed out, and that's why you saw expected value using NSLog(#"myVariable %#", self.myVariable);
Operator "==" will compare 2 objects in this case (compare both pointer and value) ==> it will return false in your case
If you want to compare primitive value of 2 NSNumbers, use following method instead (BOOL)isEqualToNumber:(NSNumber *)number;

Related

Convert NSDictionary value (id?) to NSString or NSNumber to compare it

pls help me with my trouble:
I can't compare to value to know successful result was or not.
I fetch json-object as NSDictionaty:
NSDictionary *returnDictionary = [NSJSONSerialization JSONObjectWithData:responseObject options:0 error:nil];
And after that I get value for key: code
[returnDictionary objectForKey:#"code"];
If returning value is equal 1 so that's OK, but problem is that I don't know the type value of key "code". I tried to compare id, NSString, NSNumber but all were fail. What type of object should I compare ?
Did you use the comparison operator (==) to compare your objects?
If so, you didn't compare the values of your objects but their memory addresses.
If the object returned by [returnDictionary objectForKey:#"code"] is of type NSString you should use NSString's isEqualToString:
If it returns a NSNumber instance, you could compare the intValue of that object to 1.
[[returnDictionary objectForKey:#"code"] isEqualToString:#"1"]
or
[[returnDictionary objectForKey:#"code"] intValue] == 1
You can use
[[returnDictionary objectForKey:#"code"] isKindOfClass:[NSString class]]
to check the class of the object pulled from the dictionary.
Hope it helps!
If you expect the output to be an integer, you can call intValue.
[[returnDictionary objectForKey:#"code"] intValue] == 1
Also, you can log the type of the returned object by + class; method.
NSLog(#"%#", [[returnDictionary objectForKey:#"code"] class]);
put in a breakpoint and print out the classname...
type into the debugger: po [[returnDictionary objectForKey:#"code"]className]
that will give you the class, something like _NSCFString will be a string etc...
id is something of a "cheat" in Objective-C, though one that is officially "blessed". Generally, where a method returns id you can directly use that value to invoke a method on the returned type, without having to first cast to the appropriate type -- the compiler knows to suppress "can't find that method name" type warnings/errors when the call is on an id.
Of course, if you don't know the class of the object, you don't know whose methods to call. As Pablo suggests you can use isKindOfClass to test, if you have a suspicion. Alternatively, you can log the class name of an object with NSLog(#"The class is %s", object_getClassName(someId)); or one or two other ways.

sortedArrayUsingSelector what is it doing?

I am still new to objective-c and am trying to figure out what this statement is doing exactly.
[names allKeys] sortedArrayUsingSelector:#selector(compare:)];
I know that allKeys is getting all the keys from my dictionary. I know that sortedArrayUsingSelector is sorting my array im creating. Then im calling the compare method, that is where I am lost what is this doing? From the document on apple it says that "Returns an NSComparisonResult value that indicates whether the receiver is greater than, equal to, or less than a given number." I dont understand how it is sorting based of that method.
NSArray * sortedKeys = [[names allKeys] sortedArrayUsingSelector:#selector(compare:)];
The above code returns a sorted array of the dictionary keys using the selector you provide. The selector is actually the function that will be called on the object that is being sorted in your array. In this case your array contains strings so in the actual NSArray sorting code the following would be happening,
//...
[key1 compare:key2];
//..
If you passed in a different selector lets say #selector(randomFunction:) then in the sorting code the following would happen
//..
[key1 randomFunction:key2];
//..
Since NSString does not respond to the selector randomFunction you would get an error. If you wanted to create your own type of comparison function you would need to add a category to the class that the array contains (in your case a category to NSString).
A better way to sort an array is to use a block statement.
id mySort = ^(NSString * key1, NSString * key2){
return [key1 compare:key2];
};
NSArray * sortedKeys = [[names allKeys] sortedArrayUsingComparator:mySort];
The reason it's a better way is sorting any objects is very easy to do.
id mySort = ^(MyObject * obj1, MyObject * obj2){
return [obj1.title compare:obj2.title];
};
NSArray * sortedMyObjects = [myObjects sortedArrayUsingComparator:mySort];
- (NSComparisonResult)compare:
{
// if (value of firstObject) < (value of secondObject)
// return NSOrderedAscending
// else if (value of firstObject) == (value of secondObject)
// return NSOrderedSame
// else
// return NSOrderedDescending
}
The -sortedArrayUsingSelector: method in your example calls the -compare: method on the objects in the array. For some objects Apple has already implemented a -compare: method, for example if you read through the NSString documentation, you'll find a -compare: method implemented. You can also call custom comparison methods on your own custom objects if you've implemented a comparison method in these objects. Please note the comparison method doesn't have to be called -compare:, of importance is only the return value (NSComparisonResult) and the object the method receives.
The new array contains references to the receiving array’s elements, not copies of them.
The comparator message is sent to each object in the array and has as its single argument another object in the array.
For example, an array of NSString objects can be sorted by using the caseInsensitiveCompare: method declared in the NSString class. Assuming anArray exists, a sorted version of the array can be created in this way:
NSArray *sortedArray =
[anArray sortedArrayUsingSelector:#selector(caseInsensitiveCompare:)];
You should probably be using caseInsensitiveCompare: in this situation since you are most likely ordering an array of strings (keys from a dictionary).
You've assumed that sortedArrayUsingSelector is somehow separate to the compare: part of the code. This is not the case. compare: is the selector that is used to sort the array.
The sorting method gives you back an array where each element, when sent the specified selector and the next element in the array, gives the correct sort order.
How NSArray achieves this is not public but at root, the selector you define is used to compare pairs of objects from within the array, the result of which informs their placement in the sorted array.

if statement fails with variable from CoreData managed object

I'm having some trouble with Managed Objects... imagine that.
Here is one real doozy, maybe someone can help.
So I have a managed object class called "Format" which is an entity. Anyway, it has a property called "slot" that's an NSNumber. Now the number can have values from zero to four, but if it does not have a value then I want the NSNumber object to be equal to "nil" as opposed to zero. I wasn't having any luck with that since evidently being zero is the same as being "nil." Ugh. (Is there a way to tell if the pointer is simply empty, "nil," as opposed to pointing to a zero value?)
At any rate, I tried a work-around which was to render the variable into text like so:
if(#"myFormat.slot" != #"(null)")
NSLog(#"slot==%#",myFormat.slot);
But the problem is that I got this in my log:
slot==(null)
So, OK... what the heck? If #"myFormat.slot" == #"(null)" then how the heck is that if statement resolving...?!?!
I'm truly baffled now... please someone help me out.
You won't ever get a nil back from an attribute. Instead, you get a [NSNull null] object.
In Objective-C, nil and null are not interchangeable. When you see nil you are almost looking at a dereferenced pointer. nil is intended to convey that no object has been assigned to the symbol. null by contrast is the singleton instance of [NSNull null]. It is used as a placeholder to indicate that some value, represented by an object, has not been set. In other words, a value of nil doesn't make sense in Objective-C.
In Core Data, relationships and attributes are not treated the same even though they both return objects. A relationship is a pointer to an external object and therefore can have a return nil if no object has been set on the other side of the relationship. An attribute is a value only held by an object and therefore is always represented by [NSNull null] if not set.
By default, all attributes with numerical value will return an NSNumber object initialized to zero. If you remove the default you get [NSNull null].
However, since [NSNull null] is a singleton you can use a simple pointer comparison to check for it e.g.
if (myMo.numericalAttribute == [NSNull null])...
However, that is considered bad practice.
This if(#"myFormat.slot" != #"(null)") is always true, because #"myString" creates an autoreleased string. Therefore you are checking the addresses of to different autorelease strings and (surprise) they are different.
Have you tried something like this:
if ([myNumber isEqualTo: [NSNumber numberWithInt: 0]]) self.myNumber = nil;
When comparing the contents of 2 NSString objects, use the isEqual: method or, if you need to perform a Unicode-based comparison of strings, use isEqualToString:.
If you want to set myFormat.slot to nil, do this:
myFormat.slot = nil;
To set the value of the slot attribute to zero:
myFormat.slot = [NSNumber numberWithInt:0];
To compare values wrapped in NSNumbers (e.g. check if your slot is equal to the 0 integer value), do this:
if ([myFormat.slot intValue] == 0) { // primitive type comparison
//...
}
or this:
if ([myFormat.slot isEqual:[NSNumber numberWithInt:0]]) { // object comparison
//...
}
but NOT THIS:
if (myFormat.slot == 0) { // pointer comparison!!
//...
}
To check if slot is empty (nil):
if (myFormat.slot == nil) {
//...
}
Keep in mind: Core Data standard attributes are always mapped to non-primitive values (NSString, NSDate, NSNumber). Always use isEqual:, compare: & friends when comparing objects' values. The == operator performs pointer comparison when you use it with non-primitives.

What does it mean to return an object in a method?

I still cannot understand what does it mean to return an object in a method. What would its value mean?
If I have something like this:
-(ClassName *) methodName: (int) arg {
return arg;
}
I can't understand how an object can be returned through a method as the above. If someone can help me understand.
Thanks.
You would return an object by returning an object. For example, you could ignore the argument:
- (ClassName *)methodName:(int)arg {
return [[[ClassName alloc] init] autorelease];
}
You could turn the int into an object:
- (NSNumber *)methodName:(int)arg {
return [NSNumber numberWithInt:arg];
}
You could use the argument in some calculation to determine some property of the object returned. You could process the argument and return an object indicating the status of the calculation. And so on and so on. There's a practically unlimited range of ways you could return an object from a method. All it requires is that some object be created or accessed and then returned.
The above method returns a pointer to arg which is of type ClassName*.
I assume explaining the question would assume basic knowledge of how functions are called, how passed values are pushed on stack before function call and how return values is returned from a function.
In this specific case your arg variable is part of a class, meaning that it is stored in memory that is part of the object. When you return pointer to it you are pointing to a specific area of memory within the object.
Another option is to return copy of the value. It would mean make a copy and return it.
The difference is that if you return pointer to objects internal variable that object state could be modified from outside.
If you return copy that copy can be modified and the original object will not change.
Not sure if that helps, but you are asking about very basic software development topic which assumes some background knowledge.
Maybe specify what exactly you are looking for?
Think of methods like they are functions in math. In math, sin(180) is equal to 0. sin is the method, 180 is the argument and 0 is the return value of the method. An example of sin in objective-c might go like this:
-(double) sin:(double)angleInDegrees;
{
double sinValue;
//calculate the return value here and store it in sinValue.
//for example, if angleInDegrees is 180, then set sinValue to 0
return sinValue;
}
Returning objects is exactly the same. Look at this example:
-(NSString*) sayHelloTo:(NSString*)name;
{
return [NSString stringWithFormat:#"Hello %#!", name];
}
If I were to write it like a math function, then sayHelloTo(#"Tom") is equal to #"Hello Tom!". The only difference is that #"Hello Tom!" is an NSString object, not a double.

NSMutableArray from filterUsingPredicate error

I am trying to return a subset of my NSMutableArray (MessageArray) with the following code. MessageArray contains an NSDictionary, one of the keys being FriendStatus. I get a strange error which I know is a DUH syntax issue. "error. void value not ignored as it ought to be".
-(NSMutableArray*)FriendMessageArray {
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"FriendStatus == 1"];
NSMutableArray *filtered = [MessageArray filterUsingPredicate:predicate];
return filtered;
}
"void value not ignored as it ought to be" means that a method with a signature that starts with (void) is being used to assign a value or object to a variable. What's the signature for filterUsingPredicate? does it start with (void) ?
I'm assuming "MessageArray" is an instance variable (never name instance variables this way; you should have a property called -messages and access it with self.messages). I'l further assume that it is an NSMutableArray or else you'd be getting warnings from the compiler.
NSMutableArray -filterUsingPredicate: modifies the array itself, returning void. The method you want is -filteredArrayUsingPredicate: which returns an array. The fact that the former is a verb and the latter is a noun indicates this fact even without reading the docs. Cocoa naming is extremely consistent, which is why I mention it in the first paragraph. Pay attention to the names and you will have far fewer bugs.