実際の回答はまばらだったので、Dave Delong のDDMathParserと呼ばれるオープン ソースの評価ツールを使用することになりました。
私のモデルでは、"Item" と "Formula" の両方に対して NSManagedObject をサブクラス化しました。次のような計算された読み取り専用プロパティをそれぞれ追加しました。
「MyItem.m」で
// Define dependencies of the calculated value upon other attributes, for KVO. Whenever any of the provided keypaths change, there is a need to recalculate.
+ (NSSet *)keyPathsForValuesAffectingCalculatedValue {
return [NSSet setWithObjects:@"x", @"y", @"z", @"formula.expression", nil];
}
- (double) calculatedValue {
NSError *error = nil;
NSDictionary *s = [NSDictionary dictionaryWithObjectsAndKeys: @(self.x) , @"X", @(self.y) , @"Y", @(self.z), @"Z", nil];
NSNumber *result = [[DDMathEvaluator defaultMathEvaluator] evaluateExpression:self.formula.expression withSubstitutions:s error:&error];
if (error)
NSLog(@"Error calculating value: %@", error);
else
return [result doubleValue];
}
そして私の「MyFormula.m」で:
@dynamic expressionParsingError;
+ (NSSet *)keyPathsForValuesAffectingExpression {
return [NSSet setWithObjects:@"formulaString", nil];
}
- (DDExpression *)expression {
NSError *err = nil;
DDExpression *exp = [DDExpression expressionFromString:self.volumeFormula error:&err];
self.expressionParsingError = err;
return err ? nil : exp;
}
解析された式と計算結果を保存したり、キャッシュしたりしません。不適切な数式の解析エラーを表示および報告するために、エラー オブジェクトを 1 つだけキャッシュします。DDMathParser エンジンを DDExpression に変換すると、この NSError を受け取ります。
これらのプロパティをモデルの適切な一時属性にすることもできましたが、最初はパフォーマンスが良好だったので、今はそれを行う必要はないと判断しました。私はおそらく将来いつか私の解決策を繰り返すでしょう。
次に、テーブルとアルゴリズムで、MacOS-X アプリ テーブルの列を「calculatedValue」プロパティにバインドするだけで、必要に応じて自動的に計算されます (ただし、結果はキャッシュされません)。
将来的には、DDMathParser の必要性を取り除き、NSExpression に戻すことができます。しかし --- DDMathParser を使用すると、ユーザーが数式を編集するとすぐに解析エラーを表示するなど、素晴らしいことができます。私はまた、ユーザーが偽の数字で数式をテストし、数百万の項目に適用する前に数式が正常に機能することを確認できる小さな「サンドボックス」も提供します。
私のかなり古い MacBookPro (2009) では、10000 個のアイテムを分析するのはすぐにできます。セル ベースのテーブルは、列全体を評価するのではなく、表示されている部分だけを評価することに注意してください。
これが役立つことを願っています...