我根据事务类型执行谓词以获取特定日期范围内的所有事务。
这是谓词:
NSString *predicate = [NSString stringWithFormat:@"(date >= %@ AND date < %@) AND (%@)", from, to, defaultType];
以下是完整的代码:
- (NSArray *)transactionFromMonth:(NSInteger)fromMonth toMonth:(NSInteger)toMonth ofTypes:(NSArray *)transactionTypes
{
// get the current calendar of the device
NSCalendar *calendar = [NSCalendar currentCalendar];
// create date components using current calendar
NSDateComponents *components = [[NSCalendar currentCalendar] components:NSCalendarUnitDay
| NSCalendarUnitMonth | NSCalendarUnitYear fromDate:[NSDate date]];
// get year
NSInteger currentYear = [components year];
// create fromDate (The first day of the month) using the current year, passing month, and 1 as the day
// to form the starting day of the month
// e.g when toMonth has a value of 1, then the resulting
// date will be January 1, (current year of the device's calendar)
NSDateComponents *comps = [[NSDateComponents alloc] init];
[comps setDay:1];
[comps setMonth:fromMonth];
[comps setYear:currentYear];
NSDate *from = [[NSCalendar currentCalendar] dateFromComponents:comps];
// create toDate
//
// Set your month here
[comps setMonth:toMonth];
// get the number of days of "to" month
NSRange range = [calendar rangeOfUnit:NSDayCalendarUnit
inUnit:NSMonthCalendarUnit
forDate:[calendar dateFromComponents:comps]];
[comps setDay:range.length+1];
NSDate *to = [[NSCalendar currentCalendar] dateFromComponents:comps];
NSLog(@"to Months %@", to);
NSString *defaultType = [NSString stringWithFormat:@"type = %d", [[transactionTypes objectAtIndex:0] integerValue]];
NSMutableString *types = [[NSMutableString alloc] initWithString: defaultType ];
for ( int i = 1; i < transactionTypes.count; i++ )
{
[defaultType stringByAppendingFormat:@" OR type = %d", [[transactionTypes objectAtIndex:i] integerValue] ];
}
// here is the predicate causing the error
//
//
NSString *predicate = [NSString stringWithFormat:@"(date >= %@ AND date < %@) AND (%@)", from, to, defaultType];
return [self.transaction filteredSetUsingPredicate: [NSPredicate predicateWithFormat:predicate]].allObjects;
}
以下是交易模型的声明: 注意:以下模型的.h和.m是自动生成的。
以下是示例电话:
// I want to retrieve all transaction from January 1 to January 31 in device's current calendar year of type kTransactionTypeAddFund (which has the value of 0)
[self transactionFromMonth:1 toMonth:1 ofTypes:@[ @(kTransactionTypeAddFund) ]];
结果:
原因:&#39;无法解析格式字符串&#34;(日期&gt; = 2014-12-31 16:00:00 +0000和日期&lt; 2015-01-31 16:00:00 +0000)AND(type = 0)&#34;&#39;
答案 0 :(得分:4)
您的问题是stringWithFormat:
和predicateWithFormat:
的功能不同。具体来说,predicateWithFormat:
将在stringWithFormat赢得的情况下根据需要转义和/或引用字符串。您需要使用predicateWithFormat:
创建单个谓词,然后使用连接谓词创建连接:
NSMutableArray* types = [NSMutableArray new];
for ( int i = 0; i < transactionTypes.count; i++ )
{
[types addObject:[NSPredicate predicateWithFormat:@"type = %@", [transactionTypes objectAtIndex:i]]];
}
// Make a compound predicate with "or" for all the types
NSPredicate* typePredicate = [NSCompoundPredicate orPredicateWithSubpredicates:types];
// Create the date part of the predicate
NSPredicate* datePredicate = [NSPredicate predicateWithFormat:@"(date >= %@ AND date < %@)", from, to];
// merge the type and date parts of the predicate into a single
// and predicate
NSPredicate* predicate = [NSCompoundPredicate andPredicateWithSubpredicates:@[ typePredicate, datePredicate]];
或者,更容易,只需利用谓词IN运算符...
NSPredicate* predicate = [NSPredicate predicateWithFormat:@"date >= %@ AND date < %@ AND type IN %@", from, to, transactionTypes];
答案 1 :(得分:3)
我建议你做的是(1)将最后一行分成更多的陈述,(2)删除整个stringWithFormat:
的东西,因为predicateWithFormat:
是 a格式化字符串,所以你只是混淆了额外的间接级别。这个测试编译并运行得很好:
NSPredicate *predicate =
[NSPredicate predicateWithFormat:
@"(date >= %@ AND date < %@) AND (type = %@)",
[NSDate new], [NSDate new], @0];
这表明,如果您在简单的阶段进行简化并且可以理解和调试,那么您应该能够执行您尝试执行的操作。做我在这里做的事情 - 在一行中使用{{1>}形成只是谓词。一旦你有了编译的谓词,剩下的就很容易了。
顺便提一下,请注意我传递了一个对象(一个NSNumber),其中predicateWithFormat:
是预期的。你不能在这里使用标量(比如普通的%@
)。如果您想通过0
,则需要0
。
最后一个建议:看起来你正试图形成一个复杂的谓词,其条款是有条件的,就像有时会添加额外的OR术语一样。这样做的方法是了解像NSCompoundPredicate这样的东西 - 这是它的用途。不要试图欺骗并用一根绳子完成所有操作。