I'm all quite new to Objective-C and pointers and whatnot, so go easy on me.
Basically, i have a place in my code where i extract NSDictionaries from an NSArray based on their date key.
I check for equality by doing this:
if ([[dictItem valueForKey:#"Date"] isEqualToString: date])
Strangely though, it only becomes true for one of the many objects, namely the one with the same pointer value.
How can i explicitly and beyond any doubt compare the VALUE of two strings and NOT the pointer address?
Thanks.
Edit: Perhaps i should mention that for all the comparisons on which it fails, the date has been inserted into the dictionary from a textFields text-property, if that matters.
Your code should work. Are you sure [dictItem valueForKey:#"Date"] is not nil?
Have you tried comparing without the dictionary, that is, storing one of the strings in some variable directly, just to check if that works?
Also, you might want to consider using actual NSDate objects. You can convert String to NSDate and vice versa with NSDateFormatter.
Related
I'm pretty new to iOS development, and I want to figure out if there's a good way to handle this issue. Basically, I'm making a technical calculator that returns some product specifications based on user input parameters. The product in question has specs for some, but not all user parameters, so I . In a constants file, I have a bunch of ATTEN_SPEC_X variables which are const double or const NSString *. Now, it's perfectly okay to be missing a spec, so my plan was to leverage NSArray's ability to hold different types and use introspection later to handle strings vs doubles before I report the returned specs.
Here's an incomplete example of one method I'm implementing. It's just a big conditional tree that should return a two-element array of the final values of spec and nominal.
- (NSArray *)attenuatorSwitching:(double *)attenuator{
double spec, nominal;
{...}
else if (*attenuator==0){
spec=ATTEN_SPEC_3; //this atten spec is a string!
nominal=ATTEN_NOM_3;
}
{...}
return {array of spec, nominal} //not actual obj-c code
So instead of making spec and nominal doubles, can I make them some other general type? The really important thing here is that I don't want to use any special handling within this method; another coder should be able to go back to the constants file, change ATTEN_NOM_3 to a double, and not have to retool this method at all.
Thanks.
The problem you'll run into is that NSArrays can't directly handle doubles. However, you can get around this if you start using NSNumber instances instead - you can return an NSArray * containing an NSString * and an NSNumber * with no problems. If you need even more general typing, the Objective-C type id can be used for any object instance (though still not with primitives; you can't make a double an id).
Later, when you get an array, you can use the NSObject method -isKindOfClass: to determine the type of object you're pulling out of the array, and deal with the string or number depending on the resultant type. If you need to convert your NSNumber back to a double, just use the NSNumber instance method -doubleValue to unbox your double. (+[NSNumber numberWithDouble:] goes the other way, giving you an NSNumber out of a double.)
If you're using a recent enough version of Xcode, you can even make these things literals, rather than having to litter calls to +numberWithDouble: all over the place:
return #[ #3, #"number of things" ]
I am parsing the values of Json object to my data model, and I am trying to figure out if there is any way to compare the name of the iVar's set for are the same with respect to dictionary keys. I am sure there is a good way to do that, but just can't find the method somehow.
Thanks.
It's a little hard to tell what you're asking, but I think you want Key-Value Coding. In particular, setValuesForKeysWithDictionary: will let you pass a dictionary of property or ivar names and set them for you.
I want to add items to mutable array from a dictionary. Problem is I want to check existing array items before adding new item. If same item is already there in the array, I want to replace it. else add the new item.
How could I do it?
You could perhaps use an NSMutableSet rather than an NSMutableArray. The addObject method on NSMutableSet will only "add a given object to the set, if it is not already a member."
If you'd like to check membership before adding to the set anyway, you can check the result of:
[mySet containsObject:myObjectFromDictionary]
...which returns a simple BOOL value indicating whether the set already contains an object whose isEqual method returns true when your object is passed to it.
(For a little extra functionality, NSCountedSet will keep track of the number of objects added to the "set" for which isEqual: returns true)
You could compare the result of : [yourArray indexOfObject:yourObject]; against NSNotFound to know if the object is in the array.
It will give you the index of the object to replace, or if it is equal to NSNotFound, you will add it.
Objects equality is tested with isEqual: method.
NSArray class reference.
On the face of it, both Vincent's and Rich's answers are correct.
However, there is a conceptual issue in the original question that hasn't been addressed.
Namely, that "membership in an array" via indexOfObject: (or containsObject: in a set) is ultimately done by comparing the two objects using isEqual:.
If isEqual: returns YES, then the two objects better had damned well be functionally identical in your code or else you have other, significantly more serious, problems in your design and implementation.
Thus, the real question should be "How do I detect if an object is already in an array and not add it?" and Rich's and Vincent's answer are both still correct.
I.e. you should only need to check for presence and, if present, take no action.
(Note that there are esoteric situations where replacement is actually warranted, but they are both truly esoteric and not generally used within the context of a mutable collection)
I spent some time today chasing down two bugs, and ended up fixing both of them using the same solution.
Now that I have the solution, I was hoping to get some clarity behind it.
I'm comparing an attribute from Core Data (Integer 16/NSNumber) with an Integer (ABPropertyID & ABMultiValueIdentifier).
The bug was in this comparison, and oddly enough, only showed itself after I had killed the app (from the background tray), reopened it, and run through the same process that included the comparison. Anyways...
This is what stopped working after a restart:
if (myNumber.aProperty == [NSNUmber numberWithInt:anInteger]) { /* do stuff here */ }
And these are the two solutions, which so far, are working perfectly:
if ([myNumber.aProperty integerValue] == anInteger) {/* do stuff here */ }
if ([myNumber.aProperty isEqualToNumber:[NSNumber numberWithInt:anInteger]]) { /* do stuff here */ }
To me, they all look identical. I'm always either converting the NSNumber to an integerValue, or converting the integer to an NSNumber.
Any ideas?
Do not use == to compare NSNumbers. Most of the time you'll be comparing two distinct objects, so the comparison won't evaluate to true. If you look at your if condition, notice that you're particularly comparing your property to a brand new NSNumber object.
Since NSInteger is a Cocoa wrapper for certain value types, comparing NSIntegers with == works fine.
The implementation of isEqualToNumber: probably takes the wrapped value types and compares them too.
As you said, both solutions are working...
I would prefer the first one, as it appears more readable, IMHO...
It may also be more performant, as you are comparing integers, after having converted a NSNumber to an int.
In the second one, you convert an int to an object, then you compare the two objects...
So that's a second method call, which you don't have in the first case...
Hope this helps... : )
netWorkingButtonsIndexes is the array which holds objects and
LinkedIn is a number with int data type.
[[netWorkingButtonsIndexes objectAtIndex:buttonIndex] isEqual:[NSNumber numberWithInteger:LinkedIn]]
By using the isEqual method we can compare objects with any data rtype.
I am trying to compare the following values:
gType = [[UILabel alloc]init];
if (gType = [NSString string:#"BUSINESS"]) {
I get a warning that 'NSString' may not respond to '+string:'
I am unsure what is wrong. gType is a value that I populate from a db query. Other text values from the same query show up fine in a UITableView, so I am pretty confident I have created it properly.
thx,
Your code is calling the "String" class method on the NSString class. This doesn't accept any arguments, which is your problem here.
The correct way to write your code would be something like:
if ([gType.text isEqualToString:#"BUSINESS"])
For starters, = is the assignment operator in C and does not compare anything. Secondly, even if you were using a comparison operator there, you'd be comparing pointer addresses, not the textual contents of the objects.
Read this
You're looking for:
if ([someString isEqual:#"Something else"]) { ... }
As NSD said, you have a few fundamental problems with your code there.
If you want to compare strings in Cocoa Touch, you can use the -isEqualToString: method on NSString.