NSPredicateEditor Sample Code

NSPredicateEditor Sample Code

Created By: Debasis Das (19-May-2015)

In this tutorial we will create a sample application to demonstrate the usage of NSPredicateEditor & NSPredicateEditorRowTemplate.

We will also create a custom row template by subclassing NSPredicateRowTemplate.

A NSPredicateRowTemplate normally has the following elements

  • A popup for the left expression
  • A popup for the comparison operator
  • A field (date field, text field or a constant value popup etc) or the right expression.

The custom row template will have an extra button and a text message.

The custom NSPredicateEditorRowTemplate will look like the below screen shot

Custom NSPredicateEditorRowTemplate

Custom NSPredicateEditorRowTemplate

The sample application will have the below User Interface once we are done building the application

NSPredicateEditor Sample Code

NSPredicateEditor Sample Code

NSPredicateEditor Sample Code

//  AppDelegate.h
//  KSPredicateEditor
//  Created by Debasis Das on 5/17/15.
//  Copyright (c) 2015 Knowstack. All rights reserved.

#import <Cocoa/Cocoa.h>
@interface AppDelegate : NSObject 
@end

//  AppDelegate.m
//  KSPredicateEditor

#import "AppDelegate.h"
#import "KSDepartmentsRowTemplate.h"

#define DEFAULT_PREDICATE @"firstName = 'John' " \
@"OR lastName = 'Doe' " \
@"OR dateOfBirth > CAST('01/01/1985', 'NSDate') " \
@"AND dateOfBirth <= CAST('01/01/1995', 'NSDate') " \
@"OR country = 'United States'" \
@"OR department = 'Finance'"


@interface AppDelegate ()

@property (weak) IBOutlet       NSWindow            *window;
@property (weak) IBOutlet       NSPredicateEditor   *predicateEditor;
@property (nonatomic,strong)    NSPredicate         *predicate;
@property (assign) IBOutlet     NSTextView          *queryTextField;
@end

@implementation AppDelegate

- (id)init
{
    self = [super init];
    if (self != nil) {
        _predicate = [NSPredicate predicateWithFormat:DEFAULT_PREDICATE];
    }
    return self;
}

-(IBAction)generateQuery:(id)sender
{
    [self.queryTextField setFont:[NSFont fontWithName:@"Helvetica" size:18.0]];
    [self.queryTextField setString:[self.predicateEditor.objectValue description]];
}

-(IBAction)predicateEditorAction:(id)sender{
    NSLog(@"%s",__func__);
}

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {

//This is required for the Any, All and None option in the predicate editor
    NSPredicateEditorRowTemplate *compound = [[NSPredicateEditorRowTemplate alloc] initWithCompoundTypes:@[@(NSAndPredicateType),@(NSOrPredicateType),@(NSNotPredicateType)]];

    
NSPredicateEditorRowTemplate *firstNameRowTemplate = [[NSPredicateEditorRowTemplate alloc] initWithLeftExpressions:[NSArray arrayWithObject:[NSExpression expressionForKeyPath:(@"firstName")]]
rightExpressionAttributeType:NSStringAttributeType
modifier:NSDirectPredicateModifier                                                                                                           operators:@[@(NSEqualToPredicateOperatorType), @(NSNotEqualToPredicateOperatorType)]                                         options:0];
    
NSPredicateEditorRowTemplate *lastNameRowTemplate = [[NSPredicateEditorRowTemplate alloc] initWithLeftExpressions:[NSArray arrayWithObject:[NSExpression expressionForKeyPath:(@"lastName")]]                                                               rightExpressionAttributeType:NSStringAttributeType                                                                           modifier:NSDirectPredicateModifier                                                                                           operators:@[@(NSEqualToPredicateOperatorType), @(NSNotEqualToPredicateOperatorType)]
  options:0];

  
NSArray *comparisonOperators = @[@(NSEqualToPredicateOperatorType),@(NSGreaterThanOrEqualToPredicateOperatorType),@(NSLessThanOrEqualToPredicateOperatorType),@(NSGreaterThanPredicateOperatorType),@(NSLessThanPredicateOperatorType)];
    
NSPredicateEditorRowTemplate *dateOfBirthTemplate = [[NSPredicateEditorRowTemplate alloc] initWithLeftExpressions:[NSArray arrayWithObject:[NSExpression expressionForKeyPath:(@"dateOfBirth")]]                                                          rightExpressionAttributeType:NSDateAttributeType                                                                             modifier:NSDirectPredicateModifier                                                                                           operators:comparisonOperators 
options:0];
    
NSArray *countryList = [NSArray arrayWithObjects:[NSExpression expressionForConstantValue:@"United States"],[NSExpression expressionForConstantValue:@"Mexico"],[NSExpression expressionForConstantValue:@"Brazil"],[NSExpression expressionForConstantValue:@"Canada"],nil];

NSArray *equalNotEqualOperators = [NSArray arrayWithObjects:
[NSNumber numberWithUnsignedInteger:NSEqualToPredicateOperatorType],
[NSNumber numberWithUnsignedInteger:NSNotEqualToPredicateOperatorType],nil];

NSPredicateEditorRowTemplate *countryTemplate = [[NSPredicateEditorRowTemplate alloc] initWithLeftExpressions:[NSArray arrayWithObject:[NSExpression expressionForKeyPath:(@"country")]]                                                                  rightExpressions:countryList                                                                                                 modifier:NSDirectPredicateModifier                                                                                           operators:equalNotEqualOperators
options:0];
                                                     
    NSArray * leftExpressions = [NSArray arrayWithObject:[NSExpression expressionForKeyPath:@"department"]];   
    KSDepartmentsRowTemplate * departmentCustomRowTemplate = [[KSDepartmentsRowTemplate alloc] initWithLeftExpressions:leftExpressions];

    NSArray *templates = @[compound, firstNameRowTemplate,lastNameRowTemplate,dateOfBirthTemplate,countryTemplate,departmentCustomRowTemplate];
    
    [self.predicateEditor setRowTemplates:templates];
    [self.predicateEditor setObjectValue:_predicate];
    
    NSLog(@"%@",self.predicateEditor.rowTemplates);

    /*
    //LEFT EXPRESSION
     The left expression can be created using any of the following options
     + (NSExpression *)expressionWithFormat:(NSString *)expressionFormat argumentArray:(NSArray *)arguments NS_AVAILABLE(10_6,4_0);
     + (NSExpression *)expressionWithFormat:(NSString *)expressionFormat, ...  NS_AVAILABLE(10_6,4_0);
     + (NSExpression *)expressionWithFormat:(NSString *)expressionFormat arguments:(va_list)argList NS_AVAILABLE(10_6,4_0);
     
     + (NSExpression *)expressionForConstantValue:(id)obj;    // Expression that returns a constant value
     + (NSExpression *)expressionForEvaluatedObject;    // Expression that returns the object being evaluated
     + (NSExpression *)expressionForVariable:(NSString *)string;    // Expression that pulls a value from the variable bindings dictionary
     + (NSExpression *)expressionForKeyPath:(NSString *)keyPath;    // Expression that invokes valueForKeyPath with keyPath
     + (NSExpression *)expressionForFunction:(NSString *)name arguments:(NSArray *)parameters;    // Expression that invokes one of the
     */
    
    //For creating the RIGHT EXPRESSION ATTRIBUTE TYPE the following options can be used
    /*
     NSUndefinedAttributeType = 0,
     NSInteger16AttributeType = 100,
     NSInteger32AttributeType = 200,
     NSInteger64AttributeType = 300,
     NSDecimalAttributeType = 400,
     NSDoubleAttributeType = 500,
     NSFloatAttributeType = 600,
     NSStringAttributeType = 700,
     NSBooleanAttributeType = 800,
     NSDateAttributeType = 900,
     NSBinaryDataAttributeType = 1000,
     NSTransformableAttributeType NS_ENUM_AVAILABLE(10_5,3_0) = 1800, // If your attribute is of NSTransformableAttributeType, the attributeValueClassName must be set or attribute value class must implement NSCopying.
     NSObjectIDAttributeType NS_ENUM_AVAILABLE(10_6,3_0) = 2000
     */
    
    //MODIFIER
    /*
     NSDirectPredicateModifier = 0, // Do a direct comparison
     NSAllPredicateModifier, // ALL toMany.x = y
     NSAnyPredicateModifier // ANY toMany.x = y
     */
    
    //NSPredicateEditor supports the following OPERATORS
    /*
     NSLessThanPredicateOperatorType = 0, // compare: returns NSOrderedAscending
     NSLessThanOrEqualToPredicateOperatorType, // compare: returns NSOrderedAscending || NSOrderedSame
     NSGreaterThanPredicateOperatorType, // compare: returns NSOrderedDescending
     NSGreaterThanOrEqualToPredicateOperatorType, // compare: returns NSOrderedDescending || NSOrderedSame
     NSEqualToPredicateOperatorType, // isEqual: returns true
     NSNotEqualToPredicateOperatorType, // isEqual: returns false
     NSMatchesPredicateOperatorType,
     NSLikePredicateOperatorType,
     NSBeginsWithPredicateOperatorType,
     NSEndsWithPredicateOperatorType,
     NSInPredicateOperatorType, // rhs contains lhs returns true
     NSCustomSelectorPredicateOperatorType,
     NSContainsPredicateOperatorType NS_ENUM_AVAILABLE(10_5, 3_0) = 99, // lhs contains rhs returns true
     NSBetweenPredicateOperatorType NS_ENUM_AVAILABLE(10_5, 3_0)
     */

}

- (void)applicationWillTerminate:(NSNotification *)aNotification {
    // Insert code here to tear down your application
}

@end

//  KSDepartmentsRowTemplate.h
//  KSPredicateEditor
//  Created by Debasis Das on 5/18/15.
//  Copyright (c) 2015 Knowstack. All rights reserved.

#import <Cocoa/Cocoa.h>
@interface KSDepartmentsRowTemplate : NSPredicateEditorRowTemplate
{
}

- (id) initWithLeftExpressions:(NSArray *)leftExpressions;
@end
//  KSDepartmentsRowTemplate.m

#import "KSDepartmentsRowTemplate.h"
@implementation KSDepartmentsRowTemplate

- (id) initWithLeftExpressions:(NSArray *)leftExpressions {
    NSArray * operators = [NSArray arrayWithObjects:
                           [NSNumber numberWithUnsignedInteger:NSEqualToPredicateOperatorType],
                           [NSNumber numberWithUnsignedInteger:NSNotEqualToPredicateOperatorType],
                           nil];

    NSArray *departmentList = [NSArray arrayWithObjects:
    [NSExpression expressionForConstantValue:@"Human Resources"],
    [NSExpression expressionForConstantValue:@"Finance"],
    [NSExpression expressionForConstantValue:@"Information Technology"],
    [NSExpression expressionForConstantValue:@"Sales"],
    nil];

    return [super initWithLeftExpressions:leftExpressions
                         rightExpressions:departmentList
                                 modifier:NSDirectPredicateModifier
                                operators:operators
                                  options:0];
}

- (NSArray *) templateViews {
    NSMutableArray * views = [[super templateViews] mutableCopy];
    [views addObject:[self validationView]];
    return views;
}

-(NSView *)validationView{
    NSView *view = [[NSView alloc] initWithFrame:NSMakeRect(0, 0, 400, 22.0)];
    NSButton *button = [[NSButton alloc] initWithFrame:NSMakeRect(0.0, 2.0, 70.0, 18.0)];
    [button setTitle:@"Validate"];
    [button setTarget:self];
    [button setAction:@selector(validationAction:)];
    [button setBezelStyle:NSRecessedBezelStyle];
    
    
    NSTextField *textField = [[NSTextField alloc] initWithFrame:NSMakeRect(80.0, 2.0, 220.0, 18.0)];
    [textField setBordered:NO];
    [textField setStringValue:@"This is a custom message"];
    [textField setDrawsBackground:NO];
    [textField setTextColor:[NSColor redColor]];
    
    [view addSubview:button];
    [view addSubview:textField];

    return view;
}

-(IBAction)validationAction:(id)sender
{
    NSLog(@"%s",__func__);
}



@end

The source code can be downloaded from the following location
NSPredicateEditor Sample Code, Custom NSPredicateEditorRowTemplate Sample Code

Posted in Cocoa, Objective C Tagged with: , , , ,

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

Recent Posts


Hit Counter provided by technology news