Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

IDMah

macrumors 6502
Original poster
May 13, 2011
316
11
Hi all. I can't figure this out.

I have an object let's call it foo.
foo has:

Code:
NSString name;
NSInteger footSize;
NSInteger noseSize;

and I've create a:

 NSMutableArray myFoo;

 added a bunch of foo(s) to:

 [myFoo addObject:moreFoo]; // like so //

Now I'd like to search through myFoo for someone name: @"Geoff"
and record it's index.  [myfoo objectAtIndex: X] ; 

I thought I could use indexOfObject: 

but what is the syntax: 

NSInteger findIndex;
findIndex = [myFoo indexOfObject:@"Geoff"]; // Didn't work //
findIndex = [[myFoo indexOfObject:@"Geoff"] name]; 
// returned a warning about NSUInteger  //

can I even use "indexOfObject:" ??
 
I also tried:
NSInteger cardFound = 0;
NSInteger fromIndex = 0;

for (foo *inDex in myFoo) {
		NSLog(@"started");
		if ([[inDex name] isEqualToString: @"Geoff"]) {
			cardFound = fromIndex;
			NSLog(@"card found at: %@",cardFound);
			break;
		}
                fromIndex++;
}

and that gives me an exception on the compare and exits..

thanks any help appreciated.

Ian
 
Last edited:

jiminaus

macrumors 65816
Dec 16, 2010
1,449
1
Sydney
Do as chown33 asks.

But additionally, you won't be able to indexOfObject: with an NSString unless you override isEqual: in foo to handle being given an NSString argument.

Alternatively you can use indexOfObjectPassingTest: and in the block do the comparison between a foo's name and an NSString.
 

forum user

macrumors regular
Aug 28, 2008
204
2
@IDMah
Use NSPredicate on the array. Build a predicate and use it to search for your string

- Olaf
 

IDMah

macrumors 6502
Original poster
May 13, 2011
316
11
thanks.

Thanks gang.

I looked again and the exception was a stupid NSLog mistake.
I was 'printing' a NSInteger with "%@" so it exited. over tired brains don't work too well.

I'm using 3.2.5 now and not ready to switch to Lion so "indexOfObjectPassingTest:" is out, but will remember it when I switch over.
cuz it looks easier than overriding..

unsure about "NSPredicate" since I don't what to filter, I just want to look up.
where @"Geoff" is in my array. Couldn't see/understand how it would help me find that out.

My "Brute force" method seems to do the job for now.. so might stick to that, since it's all my little brain can understand right now, and I'm probably going to restructure how the 'Data' is stored to make my life easier.. It's been difficult trying to un-think/ translate how I would do things in C.

thanks.
 

jiminaus

macrumors 65816
Dec 16, 2010
1,449
1
Sydney
I'm using 3.2.5 now and not ready to switch to Lion so "indexOfObjectPassingTest:" is out, but will remember it when I switch over. cuz it looks easier than overriding..

indexOfObjectPassingTest: was introduced in Snow Leopard (10.6) not Lion (10.7), together with blocks. XCode support for blocks was introduced in XCode 3.2.
 

IDMah

macrumors 6502
Original poster
May 13, 2011
316
11
Blocked !

jiminaus didn't know that thanks.

So I'm trying Blocks
Code:
NSInteger tryIndx = 255;
	
NSString *matchName = @"Geoff";
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF 
                                    contains[cd] %@", matchName];

	tryIndx = [myFoo indexOfObjectPassingTest:^(id obj, NSUInteger idx,
                       BOOL *stop) {
		          return [predicate evaluateWithObject:obj];
	               }];
	
	NSLog(@" index of Object found At: %i",tryIndx );

but got this...

Code:
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Can't use in/contains operator with collection <Foo: 0x4e06450> (not a collection)'

How do I indicate that I want to look in the Array myFoo of objects foo for the element (member): name?

thanks

ps is this actually a lot faster than the for loop?
Pss. Sorry this is my first real Xcode app.

Edit: Ahhh Got it .. cool

Code:
tryIndx = [  rowOne indexOfObjectPassingTest:^(id obj, NSUInteger idx, BOOL *stop) {
		return [predicate evaluateWithObject:[obj image]];
 
Last edited:

jiminaus

macrumors 65816
Dec 16, 2010
1,449
1
Sydney
Just for illustration, you can do it without predicates as well. I don't know about the performance implications of using or not using NSPredicate, you'd need to profile.

In it's simplest case:
Code:
tryIndex 
  = [myFoo indexOfObjectPassingTest:
        ^(id obj, NSUInteger idx, BOOL *stop)
        {
           [[obj image] isEqualToString:matchName];
        }
    ];

But because you've coded a case- and accent-insensitive substring match, the equivalent to your predicate is bit more.

Code:
tryIndex 
  = [myFoo indexOfObjectPassingTest:
        ^(id obj, NSUInteger idx, BOOL *stop)
        {
           NSRange r
              = [[obj image] 
                    rangeOfString:matchName
                          options:NSCaseInsensitiveSearch
                                  | NSDiacriticInsensitiveSearch
                ];
           return r.location != NSNotFound;
        }
     ];

BTW If you want to handle international strings, add the NSWidthInsenesitiveSearch option as well for your Japanese users.
 

Sykte

macrumors regular
Aug 26, 2010
223
0
ps is this actually a lot faster than the for loop?


It's not only about being faster, it's about code readability and the amount of coded needed, less code = more time for testing. :) I have found in many cases blocks are faster. I'm sure this has to do with them being copied directly onto the stack. However I suggest profiling your app and checking both ways if performance is a necessity.
 

IDMah

macrumors 6502
Original poster
May 13, 2011
316
11
NSPredicate range ??

Wow NSPredicate is pretty awesome, thanks everyone..

I've jumbled all my 2d arrays into one contiguous mass.
with Virtual boundaries, i.e if (indexX < boxSizeMaxX) then
We are in compartment two. etc.

But how would I search using NSPredicate from say:

Array from elements [0-40]
and Array elements [50-75]
... etc.

Does it, could it, save me a lot of processing time vs. a while loop?

thanks
Ian
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.