CoreData周りの技術を使っていると、たまにNSExpression
が利用できると便利そうなケースがありますが、これまでなるべく避けておりました。今回、やっと使い方を調べてテストをパスしたので、似たようなニッチなところで困っている人のために記事を残しておきます。
利用可能なオペレーター
expressionForFunction:arguments:のDiscussionで利用可能なオペレーターが列挙されています。
使い方
FUNCTION
などで包まず、add:to:(param1, param2)
という形式で指定します。
func testAddingTwoNumbersWithExpression() throws {
let exp = NSExpression(format: "add:to:(1, 2)")
let intValue = try XCTUnwrap(exp.expressionValue(with: nil, context: nil) as? Int)
XCTAssertEqual(3, intValue)
}
他のオペレーションの使い方
引数を2つ取るものは同様にxxx:yy:(param1, param2)
の記法で、
引数を1つしか取らないものはxxx:(param1)
の記法で実装します。
引数が1つの場合のサンプル
func testAbs() throws {
let exp = NSExpression(format: "abs:(-3)")
let intValue = try XCTUnwrap(exp.expressionValue(with: nil, context: nil) as? Int)
XCTAssertEqual(3, intValue)
}
注意点
パラメーターは必ず丸括弧の中に記載してください。そうでないとパースに失敗してエラーを投げます。
どこで使うか
NSBatchUpdateRequest
のpropertiesToUpdateやxcmappingmodel
でのmigration時に簡単な処理の実行させるのに使うと便利です。
おまけ: カスタム処理を利用する
カスタム処理はFUNCTION
を利用することで利用可能です。
@objc public extension NSNumber {
func threeTimes() -> NSNumber {
return NSNumber(value: self.intValue * 3)
}
}
// テストターゲット内
func testThreeTimes() throws {
let exp = NSExpression(format: "FUNCTION(1, 'threeTimes')")
let result = try XCTUnwrap(exp.expressionValue(with: nil, context: nil) as? NSNumber)
XCTAssertEqual(result, 3)
}