NSPredicate作为约束求解器?

4
我正在开发一个项目,其中包含一些比我以前使用的界面元素更复杂的动态布局。我总觉得编写复杂的代码来检查某个东西是否靠近某个位置,并在这种情况下将其向某个方向移动x%,等等,很愚蠢。编程应该尽可能声明性!
正是因为我要做的事情相当简单,我认为这是尝试新事物的好机会,我想使用NSPredicate作为一个简单的约束求解器。到目前为止,我只用NSPredicate处理非常简单的任务,但我知道它有更多的功能。
这里有什么想法、经验、示例、警告、见解可以提供帮助吗?
我将给出一个非常简单的例子,以便有具体的内容来回答。如何使用NSPredicate解决以下约束问题:
viewB.xmid = (viewB.leftEdge + viewB.width) / 2
viewB.xmid = max(300, viewA.rightEdge + 20 + viewB.width/2)

("viewB应该水平居中于坐标300上,除非它的左边缘与viewB的右边缘相距不到20个像素,在这种情况下,viewA的左边缘应保持固定在viewB的右边缘右侧20个像素处,而viewA的水平中心向右推移。") viewA.rightEdgeviewB.width可能会变化,它们是“输入变量”。
编辑:任何解决方案可能都需要使用NSExpression方法-(id)expressionValueWithObject:(id)object context:(NSMutableDictionary *)context此答案相关。

使用谓词会使得程序变慢,而直接评估条件则不会。此外,谓词只返回布尔值,你需要另一种机制来确定基于谓词结果要更新对象的哪个值。 - stefanB
是的,它会变慢,但这不是问题,只要能够实现更快速的开发。至于你关于 NSPredicates 的正确观点(正如名称所示)只评估为布尔值,请参见编辑。谢谢! - Felixyz
更明确地说,对于这个简单的例子,我会使用普通的实现。但是,我对解决问题的更灵活方式感兴趣,这可能对于更复杂的例子有用。 - Felixyz
2个回答

1

Cocoa谓词本质上是Cocoa的SQL。它们的大部分功能在于能够进行字符串搜索和比较,并且没有额外(有用的)关于您要执行的操作的设施,这是(据我所知)数字比较。我认为它们也不会产生非常可维护的代码。

常规布尔表达式在功能上等同于Cocoa谓词,您可以巧妙地重新排列和分配它们到一些漂亮命名的变量中。

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

(一个非常简单的例子……我本可以想出更好的东西)
此外,您可以将它们收起来放在一个方法中,并像使用NSPredicate一样对它们进行评估。

如何组织布尔表达式以获得可读性良好的代码的建议很不错。像那样漂亮的代码使注释变得多余。然而,NSPredicate实际上可以比仅仅进行字符串搜索更多的技巧。只需看看newacct在这里的小例子:https://dev59.com/2UnSa4cB1Zd3GeqPPZcT#1502534 - Felixyz
没错,但那基本上是它的主要用途。 - Nick Toumpelis

0
使用NSPredicate(和NSExpression)解决简单线性方程是一件轻而易举的事情,但要从那里进一步解决任意约束集合(又称线性规划),仍然是一个巨大的步骤。最有前途的前进方式是按照Chris Hanson的建议更新他的BDRuleEngine。这是一个下雨天的有趣项目。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接