Narayana Rao Routhu
Narayana Rao Routhu

Reputation: 6323

How to find if an array contains an object (not using a for loop)?

I am using below code to check ary_navigationControllerViews array contains myclass object or not its working fine but i need with out for loop.I know we have method like containsObject but how to use in this situation. Is there any way to check this condition with out using for loop.

NSArray *ary_navigationControllerViews = [[NSArray alloc] initWithArray:[self.navigationController viewControllers]];
    for(id obj_viewController in ary_navigationControllerViews) {
        if([obj_viewController isKindOfClass:[myClass  class]]) {
            //some my code
            return;
        }
    }

Upvotes: 1

Views: 2947

Answers (4)

EmptyStack
EmptyStack

Reputation: 51374

NSPredicate does this kind of jobs a lot simpler.

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"ANY SELF.class.description == %@", [[myClass class] description]];
BOOL exists =  [predicate evaluateWithObject:ary_navigationControllerViews];
if (exists) {
    //some my code
    return;
}

To get the view controller instance, you can use the following code.

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"self.class.description == %@", [[self class] description]];
NSArray *vcs = [ary_navigationControllerViews filteredArrayUsingPredicate:predicate];
if ([vcs count] > 0) {
    id vc = [vcs objectAtIndex:0];
    // Now vc is the view controller you are looking for
}

Upvotes: 12

Johannes Fahrenkrug
Johannes Fahrenkrug

Reputation: 44730

Or, based on Nekto's answer, you could also directly return the index like so:

NSArray *arr = [NSArray arrayWithObjects:[NSString stringWithFormat:@"test"], [NSNumber numberWithInt:10], [NSNull null], nil];

int index = [arr indexOfObjectPassingTest:^(id obj, NSUInteger idx, BOOL *stop) {
    if ([obj isKindOfClass:[NSNumber class]])
    {
        *stop = YES;
       return YES;
    }

    return NO;
}];
if (index != NSNotFound) 
{
    NSLog(@"contains at %d", index);
}

Enjoy.

Upvotes: 3

jrturton
jrturton

Reputation: 119242

If you really can't use a for loop for this then you'll have to use a method like indexesOfObjectsPassingTest: which applies a block to each object in the array and returns an NSIndexSet of all the items in the array. You can then use this to return a new array of just the objects that pass your test:

check = ^ (id obj, NSUInteger idx, BOOL *stop) 
{
    return [obj isKindOfClass:[myClass class]];
};

NSIndexSet *objectsInMyClass = [[self.navigationController viewControllers] indexesOfObjectsPassingTest:check];

NSArray *filteredArray = [[self.navigationController viewControllers] objectsAtIndexes:objectsInMyClass];

You could then use makeObjectsPerformSelector or similar to actually do your specific code.

Upvotes: 1

Nekto
Nekto

Reputation: 17877

You can use blocks:

NSArray *arr = [NSArray arrayWithObjects:[NSString stringWithFormat:@"test"], [NSNumber numberWithInt:10], [NSNull null], nil];
__block int index = NSNotFound;
[arr enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
    if ([obj isKindOfClass:[NSNumber class]])
    {
        index = idx;
        *stop = YES;
    }
}];
if (index != NSNotFound)
{
    NSLog(@"contains at %d", index);
}

For example, in your case:

[ary_navigationControllerViews enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
    if ([obj isKindOfClass:[myClass class]])
    {
        //some my code
        *stop = YES;
    }
}];

But I don't think that this will reduce complexity of yout code. Loops are the simplest one

Upvotes: 3

Related Questions