views:

502

answers:

1

I have store with entities that have coords (x, y, z). I want to fetch them by using predicate like @"sqrt(x*x + y*y + z*z) < distance".

Is there any way to do this?

I've tried to do thi with predicateWithFormat:

I even wrote a lot of code that looks like

NSExpression * dxExpression = [NSExpression expressionForFunction:@"from:subtract:" 
   arguments:[NSArray arrayWithObjects:
              [NSExpression expressionForConstantValue: [NSNumber numberWithFloat:currX]],
              [NSExpression expressionForKeyPath:@"self.xCoord"], nil]
                                    ];
NSExpression * dxSqrExpression = [NSExpression expressionForFunction:@"multiply:by:" 
    arguments:[NSArray arrayWithObjects:dxExpression, dxExpression, nil]
                                      ];

But it works only for not hierarchical expressions. I.e, So dxExpression works fine, but when I'm trying to use dxSqrExpression, I'm getting error

Terminating app due to uncaught exception 'NSInvalidArgumentException', 
reason: 'Unsupported function expression (-140.857 - #self.xCoord) * (-140.857 - #self.xCoord)'

I've tried without self, but this doesn't work too.

Any help will be appreciated, thanks.

+2  A: 

I don't think what you're trying to do is possible, however you could implement a generic mapping function and rewrite your @"sqrt(x*x + y*y + z*z) < distance" predicate as a function returning a BOOL which you would pass in as a selector:

@implementation NSArray(Filtering)
- (NSArray*)arrayByMappingArrayUsingSelector:(SEL)selector, ... {
  NSInvocation* invocation;
  va_list arguments;

  if (selector && [self lastObject]) {
    va_start(arguments, selector);
    invocation = [NSInvocation invocationUsingSelector:selector onTarget:[self lastObject] argumentList:arguments];
    va_end(arguments);
  }

  NSMutableArray *filteredArray = [NSMutableArray array];
  BOOL returnValue;
  for(id object in self) {
    [invocation invokeWithTarget:object];
    [invocation getReturnValue:&returnValue];

    if(ret) [filteredArray addObject:object];
  }

  return filteredArray;
}
@end
Nathan de Vries