NSExpression 使用 sqrt: 函数导致 NSInvalidArgumentException
Posted
技术标签:
【中文标题】NSExpression 使用 sqrt: 函数导致 NSInvalidArgumentException【英文标题】:NSExpression using sqrt: function results in NSInvalidArgumentException 【发布时间】:2015-05-14 04:22:41 【问题描述】:我收到一个 NSInvalidArgumentException:
*** 由于未捕获的异常“NSInvalidArgumentException”而终止应用程序,原因:“传递给 SQL 存储的函数类型不受支持”
当尝试使用 NSExpression 取嵌套 NSExpression 的平方根时,该嵌套 NSExpression 使用“multiply:by:”函数。
我的代码如下所示:
NSManagedObjectContext *context=[[BDCoreDataController sharedController] mainManagedObjectContext];
NSFetchRequest *theRequest=[[NSFetchRequest alloc] init];
[theRequest setEntity:[NSEntityDescription entityForName:@"BDCompanyEntity" inManagedObjectContext:context]];
theRequest.resultType=NSDictionaryResultType;
NSExpression *constantExpression=[NSExpression expressionForConstantValue:[NSNumber numberWithDouble:22.5]];
NSExpression *firstKeyPath=[NSExpression expressionForKeyPath:@"epsTTM"];
NSExpression *secondKeyPath=[NSExpression expressionForKeyPath:@"bookValuePerShare"];
NSExpression *firstMultiplyExpression=[NSExpression expressionForFunction:@"multiply:by:" arguments:@[firstKeyPath,secondKeyPath]];
NSExpression *secondMultiplyExpression=[NSExpression expressionForFunction:@"multiply:by:" arguments:@[firstMultiplyExpression,constantExpression]];
NSExpression *sqrtExpression=[NSExpression expressionForFunction:@"sqrt:" arguments:@[secondMultiplyExpression]];
NSExpressionDescription *expressionDescription=[[NSExpressionDescription alloc] init];
[expressionDescription setName:@"grahamNumber"];
[expressionDescription setExpression:sqrtExpression];
[expressionDescription setExpressionResultType:NSDoubleAttributeType];
[theRequest setPropertiesToFetch:@[expressionDescription,@"name"]];
NSError *fetchError;
NSArray *grahams=[context executeFetchRequest:theRequest error:&fetchError];
只尝试评估嵌套的“multiply:by:”来执行获取可以很好地使用以下代码:
NSManagedObjectContext *context=[[BDCoreDataController sharedController] mainManagedObjectContext];
NSFetchRequest *theRequest=[[NSFetchRequest alloc] init];
[theRequest setEntity:[NSEntityDescription entityForName:@"BDCompanyEntity" inManagedObjectContext:context]];
theRequest.resultType=NSDictionaryResultType;
NSExpression *constantExpression=[NSExpression expressionForConstantValue:[NSNumber numberWithDouble:22.5]];
NSExpression *firstKeyPath=[NSExpression expressionForKeyPath:@"epsTTM"];
NSExpression *secondKeyPath=[NSExpression expressionForKeyPath:@"bookValuePerShare"];
NSExpression *firstMultiplyExpression=[NSExpression expressionForFunction:@"multiply:by:" arguments:@[firstKeyPath,secondKeyPath]];
NSExpression *secondMultiplyExpression=[NSExpression expressionForFunction:@"multiply:by:" arguments:@[firstMultiplyExpression,constantExpression]];
NSExpressionDescription *expressionDescription=[[NSExpressionDescription alloc] init];
[expressionDescription setName:@"grahamNumber"];
[expressionDescription setExpression: secondMultiplyExpression];
[expressionDescription setExpressionResultType:NSDoubleAttributeType];
[theRequest setPropertiesToFetch:@[expressionDescription,@"name"]];
NSError *fetchError;
NSArray *grahams=[context executeFetchRequest:theRequest error:&fetchError];
起初我认为“sqrt” NSExpression 可能在嵌套的 NSExpression 上遇到了问题。所以我只尝试了一个常量 NSExpression。下面的代码试图只计算 sqrt NSExpression 中的一个常量。它会导致相同的 NSInvalidArguementException
NSManagedObjectContext *context=[[BDCoreDataController sharedController] mainManagedObjectContext];
NSFetchRequest *theRequest=[[NSFetchRequest alloc] init];
[theRequest setEntity:[NSEntityDescription entityForName:@"BDCompanyEntity" inManagedObjectContext:context]];
theRequest.resultType=NSDictionaryResultType;
NSExpression *constantExpression=[NSExpression expressionForConstantValue:[NSNumber numberWithDouble:22.5]];
NSExpression *sqrtExpression=[NSExpression expressionForFunction:@"sqrt:" arguments:@[constantExpression]];
NSExpressionDescription *expressionDescription=[[NSExpressionDescription alloc] init];
[expressionDescription setName:@"grahamNumber"];
[expressionDescription setExpression:sqrtExpression];
[expressionDescription setExpressionResultType:NSDoubleAttributeType];
[theRequest setPropertiesToFetch:@[expressionDescription,@"name"]];
NSError *fetchError;
NSArray *grahams=[context executeFetchRequest:theRequest error:&fetchError];
任何想法可能导致问题?
谢谢
工具人
【问题讨论】:
【参考方案1】:当使用 SQLite 存储从 Core Data 获取时,并非每个对 NSExpression
有效的表达式都有效。不幸的是,sqrt:
不支持这种用途。它可能适用于二进制存储,但这失去了 Core Data 的许多优点(例如,这意味着将所有数据一次加载到内存中)。
特别令人讨厌的是,没有记录的列表表明哪些函数支持与 Core Data 一起使用。但错误信息是完全正确的:虽然这个函数对NSExpression
使用有效,但对 SQLite 持久存储无效。
【讨论】:
好彻底的答案。谢谢汤姆。 不是我想给出的答案,因为我也可以在那里使用sqrt
,但有时这就是生活。【参考方案2】:
sqrt:
函数似乎从 v10.5 开始在 OS X 上可用,但在 ios 上不可用。
查看文档:https://developer.apple.com/library/ios/documentation/Cocoa/Reference/Foundation/Classes/NSExpression_Class/index.html#//apple_ref/occ/clm/NSExpression/expressionForFunction:arguments:
【讨论】:
感谢您的回答!但是,查看 IOS 8.3 标头,它表明 sqrt: 是受支持的函数。对于+ (NSExpression *)expressionForFunction:(NSString *)name arguments:(NSArray *)parameters;
它甚至在 iOS 4.0 中被列出:developer.limneos.net/…,但我认为它与 OS X 的标头相同,但实现不同。以上是关于NSExpression 使用 sqrt: 函数导致 NSInvalidArgumentException的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 NSExpression 使用自定义函数设置 NSFetchRequest propertiesToFetch
使用 NSExpression 时捕获 NSInvalidArgumentException 的正确方法 [重复]