Swift4にあげたら、NSExpressionのCustom Functionがunrecognized selector sent to instanceになって動かなくなったのでメモ。
NSExpressionのCustom Functionについて
NSExpressionでは以下のように文字列を計算できます。
let exp = NSExpression(format: "FUNCTION((10.0*pi*t), \'cos\')*FUNCTION((0.1*pi*t), \'cos\')")
let elements = ["pi" : Double.pi, "t" : 1.0]
exp.expressionValue(with: elements, context: nil) as? Double //0.951056516295154
このFUNCTION()で囲まれているところがCustom Functionになります。
以下のようにNSNumberを拡張してCustom Functionを作れます。(以下はSwift3でのコード)
public extension NSNumber{
func tan() -> NSNumber{
return NSNumber(value: Darwin.tan(self.doubleValue))
}
func sin() -> NSNumber{
return NSNumber(value: Darwin.sin(self.doubleValue))
}
func cos() -> NSNumber{
return NSNumber(value: Darwin.cos(self.doubleValue))
}
func atan() -> NSNumber{
return NSNumber(value: Darwin.atan(self.doubleValue))
}
func square() -> NSNumber{
return NSNumber(value: self.doubleValue * self.doubleValue)
}
}
発生した問題
先にあげた例のような式だと、
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFNumber cos]: unrecognized selector sent to instance
と出てcosという関数がないと実行時エラーが出ます。
解決方法
NSNumberのextensionの前に@objc
を入れるだけ。
@objc
public extension NSNumber{
・・・
selector周りでobjcをつけないといけないことは知ってましたが、まさかここまで飛び火するとは。Objective-Cはあまり知らないんですよね。
もしかしたら、この先動かないところが出た時、NSが付いていたらこれと同じような方法で解決できるかもしれません。
終わり