sapi
sapi

Reputation: 10224

How to determine if an object is in an array based on property value / how to use selectors?

I'm still trying to get my head around how selectors and dynamic typing work in objective c. I'm essentially trying to implement this method (shown below in python/pseudocode, same thing really :P)

def isInArray(value, array, test):
    for item in array:
        if test(item) == value:
            return True
    return False

test = lambda obj: obj.property

My intended objective-c code was:

+ (BOOL)value:(id)value:
    isInArray:(NSMutableArray *)array 
usingSelector:(SEL)selector {
    for (id item in array) {
        if (value == [item selector]) {
            return YES;
        }
    }
    return NO;
}

However, this throws a compile error, complaining that I"m comparing two pointer types (id and SEL) in the if statement.

Shouldn't that if statement be comparing the object value with the object returned from running SEL selector on the object arritem? In other words, why does it think that it's comparing an object with a SEL (I don't see what would be returning a SEL there)

Upvotes: 1

Views: 2437

Answers (2)

Anurag
Anurag

Reputation: 141879

Checkout performSelector in NSObject. The conditional would look like,

if (value == [item performSelector:selector])

By using Key Value Coding (KVC), your code could become even simpler. Say you have an array named people, where each person is an object of the class Person. A Person has firstName and lastName properties, and you want to get all people whose first name matches "John" from the people array. You could get an array of all first names, and then lookup the name "John" in that array.

NSArray *firstNames = [people valueForKey:@"firstName"];
if ([firstNames containsObject:@"John"]) {
  ..
}

Even though we're using valueForKey, it's actually making a call to the firstName method, and not directly accessing the value.

Upvotes: 3

yas375
yas375

Reputation: 3980

at least one mistake I see in method definition. There are no need to add colon after variable name (in your case value). And you should use performSelector: to make object check with your selector.

+ (BOOL)value:(id)value
    isInArray:(NSMutableArray *)array 
usingSelector:(SEL)selector {
    for (id item in array) {
        if ([item performSelector:selector] == value) {
            return YES;
        }
    }
    return NO;
}

In some cases you will need use isEqualTo: or isEqualToString: (if you work with strings) instead of == because == will return true if it's the same object.

Also, if you will need just check presence of some object in NSArray, than you could use containsObject: (return true if it is) and indexOfObjectPassingTest: (return index of object or 'NSNotFound')

Upvotes: 0

Related Questions