private NSCompoundPredicate FindMatches(string searchString) { /* * Each searchString creates an OR predicate for: name, yearIntroduced, introPrice. * Example if searchItems contains "Gladiolus 51.99 2001": * - name CONTAINS[c] "gladiolus" * - name CONTAINS[c] "gladiolus", yearIntroduced ==[c] 2001, introPrice ==[c] 51.99 * - name CONTAINS[c] "ginger", yearIntroduced ==[c] 2007, introPrice ==[c] 49.98 */ var searchItemsPredicate = new List <NSPredicate>(); /* * Below we use NSExpression represent expressions in our predicates. * NSPredicate is made up of smaller, atomic parts: * two NSExpressions (a left-hand value and a right-hand value). */ // Name field matching. var titleExpression = NSExpression.FromKeyPath(ExpressionKeys.Title); var searchStringExpression = NSExpression.FromConstant(new NSString(searchString)); var titleSearchComparisonPredicate = new NSComparisonPredicate(titleExpression, searchStringExpression, NSComparisonPredicateModifier.Direct, NSPredicateOperatorType.Contains, NSComparisonPredicateOptions.CaseInsensitive | NSComparisonPredicateOptions.DiacriticInsensitive); searchItemsPredicate.Add(titleSearchComparisonPredicate); var numberFormatter = new NSNumberFormatter { NumberStyle = NSNumberFormatterStyle.None, FormatterBehavior = NSNumberFormatterBehavior.Default }; // The `searchString` may fail to convert to a number. var targetNumber = numberFormatter.NumberFromString(searchString); if (targetNumber != null) { // Use `targetNumberExpression` in both the following predicates. var targetNumberExpression = NSExpression.FromConstant(targetNumber); // The `yearIntroduced` field matching. var yearIntroducedExpression = NSExpression.FromKeyPath(ExpressionKeys.YearIntroduced); var yearIntroducedPredicate = new NSComparisonPredicate(yearIntroducedExpression, targetNumberExpression, NSComparisonPredicateModifier.Direct, NSPredicateOperatorType.EqualTo, NSComparisonPredicateOptions.CaseInsensitive | NSComparisonPredicateOptions.DiacriticInsensitive); searchItemsPredicate.Add(yearIntroducedPredicate); // The `price` field matching. var priceExpression = NSExpression.FromKeyPath(ExpressionKeys.IntroPrice); var finalPredicate = new NSComparisonPredicate(priceExpression, targetNumberExpression, NSComparisonPredicateModifier.Direct, NSPredicateOperatorType.EqualTo, NSComparisonPredicateOptions.CaseInsensitive | NSComparisonPredicateOptions.DiacriticInsensitive); searchItemsPredicate.Add(finalPredicate); } return(NSCompoundPredicate.CreateOrPredicate(searchItemsPredicate.ToArray())); }
static NSPredicate ToPredicate(NSObject @object) { if (@object == NSNumber.FromBoolean(true)) { return(NSPredicate.FromValue(true)); } if (@object == NSNumber.FromBoolean(false)) { return(NSPredicate.FromValue(false)); } if (@object is NSArray == false) { return(null); } var array = (NSArray)@object; var objects = SubArray(array); var op = objects[0].ToString(); if (MGLPredicateOperatorTypesByJSONOperator.TryGetValue(op, out var operatorType)) { NSComparisonPredicateOptions options = 0; if (objects.Count > 3) { var collatorExpression = SubArray((NSArray)objects[3]); if (collatorExpression.Count != 2) { return(null); } var collator = (NSDictionary)collatorExpression[1]; if (false == collator.ContainsKey((NSString)"locale")) { if (collator.ValueForKey((NSString)"case-sensitive") == NSNumber.FromBoolean(false)) { options |= NSComparisonPredicateOptions.CaseInsensitive; } if (collator.ValueForKey((NSString)"diacritic-sensitive") == NSNumber.FromBoolean(false)) { options |= NSComparisonPredicateOptions.DiacriticInsensitive; } } } var subexpressions = ToSubexpressions(SubArray(objects, 1)); return(new NSComparisonPredicate( subexpressions[0], subexpressions[1], NSComparisonPredicateModifier.Direct, operatorType, options )); } switch (op) { case "!": { var subpredicates = ToSubpredicates(SubArray(objects, 1)); if (subpredicates.Count > 1) { var predicate = NSCompoundPredicate.CreateOrPredicate(subpredicates.ToArray()); return(NSCompoundPredicate.CreateNotPredicate(predicate)); } return(NSPredicate.FromValue(true)); } case "all": { var subpredicates = ToSubpredicates(SubArray(objects, 1)); if (subpredicates.Count == 2) { if (subpredicates[0] is NSComparisonPredicate leftCondition && subpredicates[1] is NSComparisonPredicate rightCondition ) { NSExpression[] limits = null; NSExpression leftConditionExpression = null; if (leftCondition.PredicateOperatorType == NSPredicateOperatorType.GreaterThanOrEqualTo && rightCondition.PredicateOperatorType == NSPredicateOperatorType.LessThanOrEqualTo ) { limits = new NSExpression[] { leftCondition.RightExpression, rightCondition.RightExpression }; leftConditionExpression = leftCondition.LeftExpression; } else if (leftCondition.PredicateOperatorType == NSPredicateOperatorType.LessThanOrEqualTo && rightCondition.PredicateOperatorType == NSPredicateOperatorType.LessThanOrEqualTo ) { limits = new NSExpression[] { leftCondition.LeftExpression, rightCondition.RightExpression }; leftConditionExpression = leftCondition.RightExpression; } else if (leftCondition.PredicateOperatorType == NSPredicateOperatorType.LessThanOrEqualTo && rightCondition.PredicateOperatorType == NSPredicateOperatorType.GreaterThanOrEqualTo ) { limits = new NSExpression[] { leftCondition.LeftExpression, rightCondition.LeftExpression }; leftConditionExpression = leftCondition.RightExpression; } else if (leftCondition.PredicateOperatorType == NSPredicateOperatorType.GreaterThanOrEqualTo && rightCondition.PredicateOperatorType == NSPredicateOperatorType.GreaterThanOrEqualTo ) { limits = new NSExpression[] { leftCondition.RightExpression, rightCondition.LeftExpression }; leftConditionExpression = leftCondition.LeftExpression; } if (limits != null && leftConditionExpression != null) { return(NSPredicate.FromFormat("%@ BETWEEN %@", leftConditionExpression, NSExpression.FromAggregate(limits))); } } } return(new NSCompoundPredicate(NSCompoundPredicateType.And, subpredicates.ToArray())); } case "any": { var subpredicates = ToSubpredicates(SubArray(objects, 1)); return(new NSCompoundPredicate(NSCompoundPredicateType.Or, subpredicates.ToArray())); } default: { var expression = ToExpression(array); return(new NSComparisonPredicate( expression, NSExpression.FromConstant(NSNumber.FromBoolean(true)), NSComparisonPredicateModifier.Direct, NSPredicateOperatorType.EqualTo, 0 )); } } }