views:

340

answers:

2

I'm working on a project which includes some slightly more complex dynamic layout of interface elements than what I'm used to. I always feel stupid writing complex code that checks if so-and-so is close to such-and-such and in that case move it x% in some direction, etc. That's just not how programming should be done. Programming should be as declarative as possible!

Precisely because what I'm going to do is fairly simple, I thought it would be a good opportunity to try something new, and I thought of using NSPredicate as a simple constraints solver. I've only used NSPredicate for very simple tasks so far, but I know that it capable of much more.

Are there any ideas, experiences, examples, warnings, insights that could be useful here?

I'll give a very simple example so there will be something concrete to answer. How could I use NSPredicate to solve the following constraints:

viewB.xmid = (viewB.leftEdge + viewB.width) / 2
viewB.xmid = max(300, viewA.rightEdge + 20 + viewB.width/2)

("viewB should be horizontally centered on coordinate 300, unless its left edge gets within 20 pixels of viewB's right edge, in which case viewA's left edge should stay fixed at 20 pixels to the right of viewB's right edge and viewA's horizontal center get pushed to the right.")

viewA.rightEdge and viewB.width can vary, and those are the 'input variables'.

EDIT: Any solution would probably have to use the NSExpression method -(id)expressionValueWithObject:(id)object context:(NSMutableDictionary *)context. This answer is relevant.

+1  A: 

Cocoa predicates are essentially a kind of SQL for Cocoa. Most of their power lies in their ability to do string searching and comparisons and have no extra (useful) facilities about what you're trying to do, which is (as far as I can tell) numeric comparisons. I don't think they make for very maintainable code either.

Regular boolean expressions are functionally equivalent to Cocoa predicates, and you can rearrange and assign them cleverly to some nicely-named variables.

if (viewAIs20PixelsAway && viewBIs30PixelsAway) {
    [viewA moveToPositionA];
} else ...

(A very simplistic example... I could've come up with something better.)

Plus, you can tuck them away in a method and evaluate them like you would do with an NSPredicate.

Nick Toumpelis
Nice suggestions for how to organize Boolean expressions to get readable code. Nice code like that makes comments superfluous. However, NSPredicate can actually pull a lot more tricks than just string searching. Just look at newacct's little example here: http://stackoverflow.com/questions/1501949/nsstring-to-equation/1502534#1502534
Felixyz
True, but that's what it's mostly for.
Nick Toumpelis
A: 

Solving simple linear equations with NSPredicate (and NSExpression) is a breeze, but to go from there to solving arbitrary collections of constraints (aka Linear Programming) is still a big step. The most promising way forward is to do what Chris Hanson suggests and update his BDRuleEngine. Fun project for a rainy day.

Felixyz