Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 5975353
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 22, 20262026-05-22T21:04:22+00:00 2026-05-22T21:04:22+00:00

Howdy! This question is pretty long so be sure to have a seat first

  • 0

Howdy! This question is pretty long so be sure to have a seat first 🙂

At one point in my code I get a string from the user, and I analyze that string. By analyzing I mean going through every character and mathcing it against a predicate the user has set in an NSPredicateEditor. The predicate is setup progamatically this way:

NSArray* keyPaths = [NSArray arrayWithObjects:
                         [NSExpression expressionForKeyPath: @"Character"],
                         [NSExpression expressionForKeyPath: @"Character Before"],
                         [NSExpression expressionForKeyPath: @"Character After"],
                         nil];
// -----------------------------------------
NSArray* constants = [NSArray arrayWithObjects:
                      [NSExpression expressionForConstantValue: @"Any letter"],
                      [NSExpression expressionForConstantValue: @"Letter (uppercase)"],
                      [NSExpression expressionForConstantValue: @"Letter (lowercase)"],
                      [NSExpression expressionForConstantValue: @"Number"],
                      [NSExpression expressionForConstantValue: @"Alphanumerical"],
                      [NSExpression expressionForConstantValue: @"Ponctuation Mark"],
                      nil];
// -----------------------------------------
NSArray* compoundTypes = [NSArray arrayWithObjects:
                          [NSNumber numberWithInteger: NSNotPredicateType],
                          [NSNumber numberWithInteger: NSAndPredicateType],
                          [NSNumber numberWithInteger: NSOrPredicateType],
                          nil];
// -----------------------------------------
NSArray* operatorsA = [NSArray arrayWithObjects:
                       [NSNumber numberWithInteger: NSEqualToPredicateOperatorType],
                       [NSNumber numberWithInteger: NSNotEqualToPredicateOperatorType],
                       nil];

NSArray* operatorsB = [NSArray arrayWithObjects:
                       [NSNumber numberWithInteger: NSInPredicateOperatorType],
                       nil];
// -----------------------------------------
NSPredicateEditorRowTemplate* template1 = [[NSPredicateEditorRowTemplate alloc] initWithLeftExpressions: keyPaths
                                                                                       rightExpressions: constants
                                                                                               modifier: NSDirectPredicateModifier 
                                                                                              operators: operatorsA
                                                                                                options: 0];

NSPredicateEditorRowTemplate* template2 = [[NSPredicateEditorRowTemplate alloc] initWithLeftExpressions: keyPaths
                                                                           rightExpressionAttributeType: NSStringAttributeType
                                                                                               modifier: NSDirectPredicateModifier 
                                                                                              operators: operatorsB
                                                                                                options: 0];

NSPredicateEditorRowTemplate* compound = [[NSPredicateEditorRowTemplate alloc] initWithCompoundTypes: compoundTypes];
// -----------------------------------------
NSArray* rowTemplates = [NSArray arrayWithObjects: template1, template2, compound, nil];

[myPredicateEditor setRowTemplates: rowTemplates];

So you can see I have three keypaths and some constants they can be compared with.
When analyzing the string I basically want to do this, in pseudocode:

originalString = [string from NSTextView]
for (char in originalString)
    bChar = [character before char]
    aChar = [character after char]

    predicate = [predicate from myPredicateEditor]

    // using predicate - problem!
    result = [evaluate predicate with:
               bChar somehow 'linked' to keypath 'Character Before'
               char 'linked' to 'Character'
               aChar 'linked' to 'Character After' // These values change, of course
              and also:
               constant "All letters" as "abc...WXYZ"
               constant "Numbers" as "0123456789"
               etc for all other constants set up  // These don't
              ]

    if (result) then do something with char, bChar and aChar

You can see where my problem basically lies:

  • ‘Character Before/After’ cannot be keypaths because of the space, but I want to keep it that way as it is more beautiful for the user (imagine having something as ‘characterBefore’ instead…)

  • Constants such as ‘Numbers’ actually represent strings like ‘0123456789’, witch I can’t display to the user as well

I was able to find a workaround to this problem, but I now it doesn’t work with every character and it is also very unefficient (in my opinion, at least). What I do is get the predicate format from the predicate, replace what I have to replace, and evaluate that new format instead. Now for some real code that explains this:

#define kPredicateSubstitutionsDict [NSDictionary dictionaryWithObjectsAndKeys: \
@"IN 'abcdefghijklmnopqrstuvwxyz'", @"== \"Letter (lowercase)\"", \
@"IN 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'", @"== \"Letter (uppercase)\"", \
@"IN 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'", @"== \"Any letter\"", \
@"IN '1234567890'", @"== \"Number\"", \
@"IN 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890'", @"== \"Alphanumerical\"", \
@"IN ',.;:!?'", @"== \"Ponctuation Mark\"", \
\
@"MATCHES '[^a-z]'"         , @"!= \"Letter (lowercase)\"", \
@"MATCHES '[^A-Z]'"         , @"!= \"Letter (uppercase)\"", \
@"MATCHES '[^a-zA-Z]'"      , @"!= \"Any letter\"", \
@"MATCHES '[^0-9]'"         , @"!= \"Number\"", \
@"MATCHES '[^a-zA-Z0-9]'"   , @"!= \"Alphanumerical\"", \
@"MATCHES '[^,\.;:!\?]'"  , @"!= \"Ponctuation Mark\"", \
\
nil]

// NSPredicate* predicate is setup in another place
// NSString* originalString is also setup in another place
NSString* predFormat = [predicate predicateFormat];
for (NSString* key in [kPredicateSubstitutionsDict allKeys]) {
    prefFormat = [predFormat stringByReplacingOccurrencesOfString: key withString: [kPredicateSubstitutionsDict objectForKey: key]];
}

for (NSInteger i = 0; i < [originalString length]; i++) {
    NSString* charString = [originalString substringWithRange: NSMakeRange(i, 1)];
    NSString* bfString;
    NSString* afString;

    if (i == 0) {
            bfString = @"";
    }
    else {
            bfString = [originalString substringWithRange: NSMakeRange(i - 1, 1)];
    }

    if (i == [originalString length] - 1) {
            afString = @"";
    }
    else {
            afString = [originalString substringWithRange: NSMakeRange(i + 1, 1)];
    }

    predFormat = [predFormat stringByReplacingOccurrencesOfString: @"Character Before" withString: [NSString stringWithFormat: @"\"%@\"", bfString]];
    predFormat = [predFormat stringByReplacingOccurrencesOfString: @"Character After" withString: [NSString stringWithFormat: @"\"%@\"", afString]];
    predFormat = [predFormat stringByReplacingOccurrencesOfString: @"Character" withString: [NSString stringWithFormat: @"\"%@\"", charString]];

    NSPredicate* newPred = [NSPredicate predicateWithFormat: predFormat];
    if ([newPred evaluateWithObject: self]) { // self just so I give it something (nothing is actually gotten from self)
        // if predicate evaluates to true, then do something exciting!
    }
}

So, here you go, this is a simplified version of what I am doing. If you see any typos, most probably they’re not in my code, because I’ve edited this quite a bit so it would be simpler.

To summarize:

  • I need to evaluate the predicate the user makes against many characters, modifying it quite a bit, while trying to be as efficient as possible
  • The problems I find with my approach are:

    • I don’t think it’s clean at all
    • I have no guarantee that it will work on every case (when one of the character is a newline/enter character, the predicate raises an error saying it can’t understand the format)

That’s all folks! Thanks for reading thus far. May your god be with you when solving this mess!

EDIT: Just to clarify things abut, I would add that what seems the trigger to this problem is the fact that I cannot, right at the start when I setup the predicate editor, define one constant with a name (that gets displayed to the user) and a value that represents that constant and gets inserted in the predicate format. The same thing for keypaths: if I could have one display name, and then one value that would be those var strings for predicate ($VAR or whatever it is) all the problems would be solved. If this is possible, please tell me how. If it is impossible, then please focus on the other problems I describe.

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-22T21:04:23+00:00Added an answer on May 22, 2026 at 9:04 pm

    So the main question:

    Can you build an NSPredicateEditorRowTemplate that uses different constants than what’s displayed in the user interface?

    Answer: yes. You used to be able to set this up in Interface Builder, but my attempts to do so in Xcode 4 have been unsuccessful. It’s possible that the capability was removed in the IB => Xcode 4 merge.

    Fortunately, you can do it in code. Unfortunately, it requires an NSPredicateEditorRowTemplate subclass. I haven’t found a way to do it without such a subclass.

    The gist is to override -templateViews in your row template, and do something like this:

    - (NSArray *)templateViews {
      NSArray *views = [super templateViews];
      // views[0] is the left-hand popup
      // views[1] is the operator popup
      // views[2] is the right-hand side (textfield, popup, whatever)
      NSPopUpButton *left = [views objectAtIndex:0];
      NSArray *items = [left itemArray];
      for (NSMenuItem *item in items) {
        //the representedObject of the item is the expression that will be used in the predicate
        NSExpression *keyPathExpression = [item representedObject];
    
        //we can alter the -title of the menuItem without altering the expression object
        if ([[keyPathExpression keyPath] isEqual:@"before"]) {
          [item setTitle:@"Character Before"];
        } else if ([[keyPathExpression keyPath] isEqual:@"after"]) {
          [item setTitle:@"Character After"];
        }
      }
      return views;
    }
    

    And voilá! A popup in your predicate editor where the title does not match the keypath.

    edit

    The other way to solve this (without subclassing!) would be to put your custom text in a .strings file and “localize” your editor to English (or whatever language you want).

    • Localizing NSPredicateEditor
    • Followup to Localizing NSPredicateEditor

    Imagine this situation: a user puts in the predicate editor this expression Character/is not/Number. The format for that predicate would be “character != “0123456789” This is always true, even if the character is a number! How do I “replace” these operators: is/is not with their real functions IN/NOT (IN …)?

    If you were to express these comparisons in a predicate, you probably wouldn’t use != and ==. Likely, you’d want to do something like:

    character MATCHES '[0-9]'
    

    And one of:

    character MATCHES '[^0-9]'
    NOT(character MATCHES '[0-9]')
    

    For this, the way that I can think of to do this would be to have two separate row templates. One would recognize and display predicates in the first format (MATCHES '[0-9]'), and the second would recognize and display the negation. You’re starting to get into the weird realm of NSPredicateEditorRowTemplates, I think. I’m still not really sure what you’re trying to accomplish and why you want to be matching every character of a string against a predicate, but whatever.

    For more information on how to create custom row templates, check out these two blog posts:

    • Creating a simple NSPredicateEditorRowTemplate
    • Creating an advanced NSPredicateEditorRowTemplate
    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

I would like to slice random letters from a string. Given s="howdy" I would
Howdy! I'm working on an old project from one of my programming courses and
I wrote the following code: public class A { protected string Howdy = "Howdy!";
Howdy fellas, this one is gonna be a doozy: So for awhile I've been
Howdy, I am trying to understand this method signature: public <K> Map<K, String> getMulti(Serializer<K>
Howdy -- Long time reader, first time questioner. :) I could really use some
Howdy, I have a DataRow pulled out of a DataTable from a DataSet. I
Howdy all, I have a weird situation. I have a C++ code that overloads
I am playing around with the example from here ; esp. I have this
EDIT: This question is solved, but I can't accept my own answer just yet.

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.