Abstracting a group of commonly named Selectors


Sandor Szatmari
 

I have a certain group of selectors that all follow a strict naming convention,

-(Status)parseXYZ
-(Status)parseRST

All have one line that does the same thing and return a scalar (enum) as a result.
Each method would do something XYZ or RST and return their status

There are about 200 of these… it’s quite annoying to maintain and look at this boiler plate interface. It should not be necessary, I hope.

I would like to abstract them using something like:
-doesNotRecognizeSelector:
or
-forwardInvocation:
or
By some other means, which I cannot conceive of…

The issue I don’t understand is, how would I return the scalar to the original caller once one of the methods has received the program flow. Neither of these methods return anything.

Is what I want to do possible?
If so, what should I be looking at?

Sandor


Alex Zavatone
 

Would it be possible to put them in an array or dictionary as NSStrings and use performSelector on one of them if it is present within the array or dict?

On Jul 20, 2020, at 12:11 PM, Sandor Szatmari <admin.szatmari.net@gmail.com> wrote:

I have a certain group of selectors that all follow a strict naming convention,

-(Status)parseXYZ
-(Status)parseRST

All have one line that does the same thing and return a scalar (enum) as a result.
Each method would do something XYZ or RST and return their status

There are about 200 of these… it’s quite annoying to maintain and look at this boiler plate interface. It should not be necessary, I hope.

I would like to abstract them using something like:
-doesNotRecognizeSelector:
or
-forwardInvocation:
or
By some other means, which I cannot conceive of…

The issue I don’t understand is, how would I return the scalar to the original caller once one of the methods has received the program flow. Neither of these methods return anything.

Is what I want to do possible?
If so, what should I be looking at?

Sandor


Sandor Szatmari
 

Alex,

Thanks for the idea. I not sure how that helps me get the return value back to the original caller. Am I missing your point?

Here’s more details, in pseudo code

// Controller class
SEL aSel
do

aSel = lookUpSel (i.e. parseXYZ)
NSInvocation *n = // make invocation with aSel
[n setTarget: ModelClass]
[n invoke]
Status s = success // I’m an optimist
[n getReturnValue:&s]

while more_sels

… Meanwhile…

// ModelClass
-(Status)parseXYZ
{
// do the same thing for each parse method
return [self parse:XYZ]
}

-(Status)parseRST
{
// do the same thing for each parse method
return [self parse:RST]
}

————

I want to change model class to do this
// remove parse SELs i.e. remove parse[A-Z]{3} methods

// replace with something like
-doesNotRespondToSelector:(SEL)aSel
{
NSString *sel = NSStringFromSelector(aSel)

if ( sel has prefix ‘parse’ )
{
NSString *selCmd = [sel subStringFromIndex:5] // remove prefix ‘parse’. e.g. ‘RST’ remains
Status s = [self parse:selCmd]

// how do I return ‘s’ to the original caller??? The Controller

}
else
[super doesNotRespondToSelector:aSel]
}


Sandor

On Jul 20, 2020, at 13:27, Alex Zavatone via groups.io <zav=mac.com@groups.io> wrote:

Would it be possible to put them in an array or dictionary as NSStrings and use performSelector on one of them if it is present within the array or dict?

On Jul 20, 2020, at 12:11 PM, Sandor Szatmari <admin.szatmari.net@gmail.com> wrote:

I have a certain group of selectors that all follow a strict naming convention,

-(Status)parseXYZ
-(Status)parseRST

All have one line that does the same thing and return a scalar (enum) as a result.
Each method would do something XYZ or RST and return their status

There are about 200 of these… it’s quite annoying to maintain and look at this boiler plate interface. It should not be necessary, I hope.

I would like to abstract them using something like:
-doesNotRecognizeSelector:
or
-forwardInvocation:
or
By some other means, which I cannot conceive of…

The issue I don’t understand is, how would I return the scalar to the original caller once one of the methods has received the program flow. Neither of these methods return anything.

Is what I want to do possible?
If so, what should I be looking at?

Sandor




Alex Zavatone
 

Well, I’m guessing here, but can’t you construct the method and use a perform selector, get the result and return it?

It seems like you are making methods, performing them, then need to perform methods within that, right? Can’t you simplify that? Or somehow define what becomes parsed in the method?

It seems like this can be simplified.

On Jul 20, 2020, at 2:47 PM, Sandor Szatmari <admin.szatmari.net@gmail.com> wrote:

Alex,

Thanks for the idea. I not sure how that helps me get the return value back to the original caller. Am I missing your point?

Here’s more details, in pseudo code

// Controller class
SEL aSel
do

aSel = lookUpSel (i.e. parseXYZ)
NSInvocation *n = // make invocation with aSel
[n setTarget: ModelClass]
[n invoke]
Status s = success // I’m an optimist
[n getReturnValue:&s]

while more_sels

… Meanwhile…

// ModelClass
-(Status)parseXYZ
{
// do the same thing for each parse method
return [self parse:XYZ]
}

-(Status)parseRST
{
// do the same thing for each parse method
return [self parse:RST]
}

————

I want to change model class to do this
// remove parse SELs i.e. remove parse[A-Z]{3} methods

// replace with something like
-doesNotRespondToSelector:(SEL)aSel
{
NSString *sel = NSStringFromSelector(aSel)

if ( sel has prefix ‘parse’ )
{
NSString *selCmd = [sel subStringFromIndex:5] // remove prefix ‘parse’. e.g. ‘RST’ remains
Status s = [self parse:selCmd]

// how do I return ‘s’ to the original caller??? The Controller

}
else
[super doesNotRespondToSelector:aSel]
}


Sandor

On Jul 20, 2020, at 13:27, Alex Zavatone via groups.io <zav=mac.com@groups.io> wrote:

Would it be possible to put them in an array or dictionary as NSStrings and use performSelector on one of them if it is present within the array or dict?

On Jul 20, 2020, at 12:11 PM, Sandor Szatmari <admin.szatmari.net@gmail.com> wrote:

I have a certain group of selectors that all follow a strict naming convention,

-(Status)parseXYZ
-(Status)parseRST

All have one line that does the same thing and return a scalar (enum) as a result.
Each method would do something XYZ or RST and return their status

There are about 200 of these… it’s quite annoying to maintain and look at this boiler plate interface. It should not be necessary, I hope.

I would like to abstract them using something like:
-doesNotRecognizeSelector:
or
-forwardInvocation:
or
By some other means, which I cannot conceive of…

The issue I don’t understand is, how would I return the scalar to the original caller once one of the methods has received the program flow. Neither of these methods return anything.

Is what I want to do possible?
If so, what should I be looking at?

Sandor





Gary L. Wade
 

You might want to consider using valueForUndefinedKey: and parse it to know which value you care about, and then return the value through NSValue, which can encapsulate any value, although a number/enum mapping might be sufficient.

On Jul 20, 2020, at 12:47 PM, Sandor Szatmari <admin.szatmari.net@...> wrote:

Alex,

Thanks for the idea.  I not sure how that helps me get the return value back to the original caller.   Am I missing your point?

Here’s more details, in pseudo code

// Controller class
SEL aSel
do

aSel = lookUpSel (i.e. parseXYZ)
NSInvocation *n = // make invocation with aSel
[n setTarget: ModelClass]
[n invoke]
Status s = success // I’m an optimist
[n getReturnValue:&s]

while more_sels

… Meanwhile…

// ModelClass
-(Status)parseXYZ
{
 // do the same thing for each parse method
 return [self parse:XYZ]
}

-(Status)parseRST
{
 // do the same thing for each parse method
 return [self parse:RST]
}

————

I want to change model class to do this
// remove parse SELs  i.e. remove parse[A-Z]{3} methods

// replace with something like
-doesNotRespondToSelector:(SEL)aSel
{
 NSString *sel = NSStringFromSelector(aSel)

 if ( sel has prefix ‘parse’ )
 {
   NSString *selCmd = [sel subStringFromIndex:5] // remove prefix ‘parse’. e.g.  ‘RST’ remains
   Status s = [self parse:selCmd]

   // how do I return ‘s’ to the original caller??? The Controller

 }
 else
   [super doesNotRespondToSelector:aSel]
}


Sandor

On Jul 20, 2020, at 13:27, Alex Zavatone via groups.io <zav@...> wrote:

Would it be possible to put them in an array or dictionary as NSStrings and use performSelector on one of them if it is present within the array or dict?

On Jul 20, 2020, at 12:11 PM, Sandor Szatmari <admin.szatmari.net@...> wrote:

I have a certain group of selectors that all follow a strict naming convention,

-(Status)parseXYZ
-(Status)parseRST

All have one line that does the same thing and return a scalar (enum) as a result.
Each method would do something XYZ or RST and return their status

There are about 200 of these… it’s quite annoying to maintain and look at this boiler plate interface.  It should not be necessary, I hope.

I would like to abstract them using something like:
 -doesNotRecognizeSelector:
 or
 -forwardInvocation:
 or
 By some other means, which I cannot conceive of…

The issue I don’t understand is, how would I return the scalar to the original caller once one of the methods has received the program flow.  Neither of these methods return anything.

Is what I want to do possible?
If so, what should I be looking at?

Sandor


Sandor Szatmari
 

Alex,

On Jul 20, 2020, at 15:51, Alex Zavatone via groups.io <zav=mac.com@groups.io> wrote:

Well, I’m guessing here, but can’t you construct the method and use a perform selector, get the result and return it?
I am proposing letting the runtime handle the fact the object does not respond to the selector. So, under this assumption I am inside one of two methods:

-doesNotRespondToSelector: or -forwardInvocation:

Both of which have a void return. So I don’t see how I can return data to the original caller… I’m not sure there’s a way to do it, but was hoping to be unaware of how to use these methods, or an alternate means of generically responding to selectors.


It seems like you are making methods, performing them, then need to perform methods within that, right? Can’t you simplify that?
Unfortunately, this is code (The controller) at the heart of a framework and many classes depend on it. I can’t justify changing that code. But I can consider writing a new model (one with lot’s of redundant selectors) in an new way.

Thanks for your ideas!

Sandor

Or somehow define what becomes parsed in the method?

It seems like this can be simplified.

On Jul 20, 2020, at 2:47 PM, Sandor Szatmari <admin.szatmari.net@gmail.com> wrote:

Alex,

Thanks for the idea. I not sure how that helps me get the return value back to the original caller. Am I missing your point?

Here’s more details, in pseudo code

// Controller class
SEL aSel
do

aSel = lookUpSel (i.e. parseXYZ)
NSInvocation *n = // make invocation with aSel
[n setTarget: ModelClass]
[n invoke]
Status s = success // I’m an optimist
[n getReturnValue:&s]

while more_sels

… Meanwhile…

// ModelClass
-(Status)parseXYZ
{
// do the same thing for each parse method
return [self parse:XYZ]
}

-(Status)parseRST
{
// do the same thing for each parse method
return [self parse:RST]
}

————

I want to change model class to do this
// remove parse SELs i.e. remove parse[A-Z]{3} methods

// replace with something like
-doesNotRespondToSelector:(SEL)aSel
{
NSString *sel = NSStringFromSelector(aSel)

if ( sel has prefix ‘parse’ )
{
NSString *selCmd = [sel subStringFromIndex:5] // remove prefix ‘parse’. e.g. ‘RST’ remains
Status s = [self parse:selCmd]

// how do I return ‘s’ to the original caller??? The Controller

}
else
[super doesNotRespondToSelector:aSel]
}


Sandor

On Jul 20, 2020, at 13:27, Alex Zavatone via groups.io <zav=mac.com@groups.io> wrote:
Would it be possible to put them in an array or dictionary as NSStrings and use performSelector on one of them if it is present within the array or dict?

On Jul 20, 2020, at 12:11 PM, Sandor Szatmari <admin.szatmari.net@gmail.com> wrote:

I have a certain group of selectors that all follow a strict naming convention,

-(Status)parseXYZ
-(Status)parseRST

All have one line that does the same thing and return a scalar (enum) as a result.
Each method would do something XYZ or RST and return their status

There are about 200 of these… it’s quite annoying to maintain and look at this boiler plate interface. It should not be necessary, I hope.

I would like to abstract them using something like:
-doesNotRecognizeSelector:
or
-forwardInvocation:
or
By some other means, which I cannot conceive of…

The issue I don’t understand is, how would I return the scalar to the original caller once one of the methods has received the program flow. Neither of these methods return anything.

Is what I want to do possible?
If so, what should I be looking at?

Sandor







Sandor Szatmari
 

Gary, 

On Jul 20, 2020, at 15:53, Gary L. Wade <garywade@...> wrote:

You might want to consider using valueForUndefinedKey:

interesting… 

and parse it to know which value you care about, and then return the value through NSValue, which can encapsulate any value, although a number/enum mapping might be sufficient.

I’ll have to see if Returning an NSValue wrapped scalar translates to the scalar result on the other side when I call -getReturnValue: 

Thanks!

Sandor


On Jul 20, 2020, at 12:47 PM, Sandor Szatmari <admin.szatmari.net@...> wrote:

Alex,

Thanks for the idea.  I not sure how that helps me get the return value back to the original caller.   Am I missing your point?

Here’s more details, in pseudo code

// Controller class
SEL aSel
do

aSel = lookUpSel (i.e. parseXYZ)
NSInvocation *n = // make invocation with aSel
[n setTarget: ModelClass]
[n invoke]
Status s = success // I’m an optimist
[n getReturnValue:&s]

while more_sels

… Meanwhile…

// ModelClass
-(Status)parseXYZ
{
 // do the same thing for each parse method
 return [self parse:XYZ]
}

-(Status)parseRST
{
 // do the same thing for each parse method
 return [self parse:RST]
}

————

I want to change model class to do this
// remove parse SELs  i.e. remove parse[A-Z]{3} methods

// replace with something like
-doesNotRespondToSelector:(SEL)aSel
{
 NSString *sel = NSStringFromSelector(aSel)

 if ( sel has prefix ‘parse’ )
 {
   NSString *selCmd = [sel subStringFromIndex:5] // remove prefix ‘parse’. e.g.  ‘RST’ remains
   Status s = [self parse:selCmd]

   // how do I return ‘s’ to the original caller??? The Controller

 }
 else
   [super doesNotRespondToSelector:aSel]
}


Sandor

On Jul 20, 2020, at 13:27, Alex Zavatone via groups.io <zav@...> wrote:

Would it be possible to put them in an array or dictionary as NSStrings and use performSelector on one of them if it is present within the array or dict?

On Jul 20, 2020, at 12:11 PM, Sandor Szatmari <admin.szatmari.net@...> wrote:

I have a certain group of selectors that all follow a strict naming convention,

-(Status)parseXYZ
-(Status)parseRST

All have one line that does the same thing and return a scalar (enum) as a result.
Each method would do something XYZ or RST and return their status

There are about 200 of these… it’s quite annoying to maintain and look at this boiler plate interface.  It should not be necessary, I hope.

I would like to abstract them using something like:
 -doesNotRecognizeSelector:
 or
 -forwardInvocation:
 or
 By some other means, which I cannot conceive of…

The issue I don’t understand is, how would I return the scalar to the original caller once one of the methods has received the program flow.  Neither of these methods return anything.

Is what I want to do possible?
If so, what should I be looking at?

Sandor


Jeff Laing
 

You really haven't provided enough information about the caller, and you've skipped over the C programmers favourite answer. Presumably you actually NEED all those seperate selectors and can't just change the caller to call a common handler. Second, what's wrong with:

#define IMPLEMENT(m) -(mytype)parse##m { return [self parse:m]; }
IMPLEMENT(XYZ)
IMPLEMENT(ABC)


Sandor Szatmari
 

Jeff,

On Jul 20, 2020, at 17:14, Jeff Laing <jefflaing@...> wrote:



You really haven't provided enough information about the caller, and you've skipped over the C programmers favourite answer. Presumably you actually NEED all those seperate selectors and can't just change the caller to call a common handler. Second, what's wrong with:

#define IMPLEMENT(m) -(mytype)parse##m { return [self parse:m]; }
IMPLEMENT(XYZ)
IMPLEMENT(ABC)

Thanks for the idea… it might be a good choice… as for additional details.

The caller can be seen as a controller.  It dynamically allocates model (parser) classes based on context.  

The model classes define the -parse### that are available by implementing a protocol (for consistency).  So, all of these selectors are already accessible in an array of dictionaries returned by the model.

The controller then asks the model for it’s available parsers and the iterates over them -invoking each one, collects a cumulative Status, and provides an overall result.

So, the selectors are already defined In this array, then I have to implement each one as a method which is one line: red two nested calls, with a constant.  So, 99% the same, save the context (constant) of which parse method is being invoked.  Historically these methods were not one line.  But parsing newer data formats (XML) leaves less individualized code in each parse method.

Now, I can’t change this design, there’s no justifiable gains from that.  I do have the opportunity to rethink how the components of this design are stitched together for this new model, and would like less unnecessarily redundant code, if the cost of achieving this is not too great.

I hope these additional details are helpful…

Thanks,
Sandor


Jeff Laing
 

In the designated initialise of your Parser class, you can use class_addMethod to add whatever you like to your instance's class.

https://developer.apple.com/documentation/objectivec/1418901-class_addmethod?language=objc

The method implementation gets called with the selector as its second argument and you can cut the string up at runtime to then call your Parse. Here's a snippet from an app I did in the past that wanted to dynamically adjust to any entries that were added to a popup menu in Interface Builder. It iterates over the popup, and for every entry present, looks for then adds a dynamic method called _popup.

        IMP popup_imp = class_getMethodImplementation([self class], @selector(_popup00:));
...
        for (NSArray *item in popup) {
                // make sure that we implement the required method
                SEL sel = NSSelectorFromString([NSString stringWithFormat:@"_popup%02ld:",(long)[menuItems count]]);
                if (![self respondsToSelector:sel]) {
                        class_addMethod([self class], sel, popup_imp, "v@:@");  // -(void)method:(id)argument;
                }

The implementation of the method gets the name of the selector using set_getName, then punts across to the actual code.

- (void)_popup00:(id)sender {
//          01234567
        const char *name = sel_getName(_cmd);
        const int idx = atoi(name+6);
        id resp = [self.popupResponders objectAtIndex:idx];
        [resp callWithArrayOfArgs:self.popupArguments];
}

Extracting your specific token from the message is just name+. This example is using (void) but it should work just fine - you aren't using the "no such method" path, you are just binding the method really late in the compile/link/run process...


Sandor Szatmari
 

Jeff,

So what you’re suggesting is…

1. Define a template implementation
2. Associate each selector pattern with that implementation

That seems like it should work.  I’ll give it a try and let you know how it goes…

Thanks,
Sandor

On Jul 21, 2020, at 17:10, Jeff Laing <jefflaing@...> wrote:



In the designated initialise of your Parser class, you can use class_addMethod to add whatever you like to your instance's class.

https://developer.apple.com/documentation/objectivec/1418901-class_addmethod?language=objc

The method implementation gets called with the selector as its second argument and you can cut the string up at runtime to then call your Parse. Here's a snippet from an app I did in the past that wanted to dynamically adjust to any entries that were added to a popup menu in Interface Builder. It iterates over the popup, and for every entry present, looks for then adds a dynamic method called _popup.

        IMP popup_imp = class_getMethodImplementation([self class], @selector(_popup00:));
...
        for (NSArray *item in popup) {
                // make sure that we implement the required method
                SEL sel = NSSelectorFromString([NSString stringWithFormat:@"_popup%02ld:",(long)[menuItems count]]);
                if (![self respondsToSelector:sel]) {
                        class_addMethod([self class], sel, popup_imp, "v@:@");  // -(void)method:(id)argument;
                }

The implementation of the method gets the name of the selector using set_getName, then punts across to the actual code.

- (void)_popup00:(id)sender {
//          01234567
        const char *name = sel_getName(_cmd);
        const int idx = atoi(name+6);
        id resp = [self.popupResponders objectAtIndex:idx];
        [resp callWithArrayOfArgs:self.popupArguments];
}

Extracting your specific token from the message is just name+. This example is using (void) but it should work just fine - you aren't using the "no such method" path, you are just binding the method really late in the compile/link/run process...


Sandor Szatmari
 

Jeff,

Works great!  See my implementation below…
The one thing I wasn’t sure about was the types array argument for class_addMethod() The fourth param…
I used ‘i’ to specify the return type of integer.  The return type is an enum.  Wasn’t sure if there was a better choice
This removed a ton of unnecessarily redundant code! 

-(id)init
{
self = [super init];
if ( self != nil )
{
IMP parser_imp = class_getMethodImplementation([self class], @selector(parseStep) );
for ( SelectorStep *step in [self parseSteps] )
{
SEL sel = step.selector;
if ( [self respondsToSelector:sel] == NO )
class_addMethod( [self class], sel, parser_imp, "i@:" );
}
}
return self;
}

// --------------------------------------------

-(ParserStepStatus)parseStep
{
const char *selName = sel_getName(_cmd);
NSString *table = [NSString stringWithCString:selName
       encoding:NSUTF8StringEncoding];
if ( [table isEqualToString:@"parseRoutePartitions"] )
NSLog( @"Stop" );
NSAssert1( [table hasPrefix:@"parse"], @"Selector must start with parse. Bad Selector: '%@'", table );
table = [[table substringFromIndex:5] snakeCase];
return [self parseStepByNameWithParams:[self stepDictForTableName:table]];
}

Sandor

On Jul 21, 2020, at 19:56, Sandor Szatmari via groups.io <admin.szatmari.net@...> wrote:

Jeff,

So what you’re suggesting is…

1. Define a template implementation
2. Associate each selector pattern with that implementation

That seems like it should work.  I’ll give it a try and let you know how it goes…

Thanks,
Sandor

On Jul 21, 2020, at 17:10, Jeff Laing <jefflaing@...> wrote:



In the designated initialise of your Parser class, you can use class_addMethod to add whatever you like to your instance's class.

https://developer.apple.com/documentation/objectivec/1418901-class_addmethod?language=objc

The method implementation gets called with the selector as its second argument and you can cut the string up at runtime to then call your Parse. Here's a snippet from an app I did in the past that wanted to dynamically adjust to any entries that were added to a popup menu in Interface Builder. It iterates over the popup, and for every entry present, looks for then adds a dynamic method called _popup.

        IMP popup_imp = class_getMethodImplementation([self class], @selector(_popup00:));
...
        for (NSArray *item in popup) {
                // make sure that we implement the required method
                SEL sel = NSSelectorFromString([NSString stringWithFormat:@"_popup%02ld:",(long)[menuItems count]]);
                if (![self respondsToSelector:sel]) {
                        class_addMethod([self class], sel, popup_imp, "v@:@");  // -(void)method:(id)argument;
                }

The implementation of the method gets the name of the selector using set_getName, then punts across to the actual code.

- (void)_popup00:(id)sender {
//          01234567
        const char *name = sel_getName(_cmd);
        const int idx = atoi(name+6);
        id resp = [self.popupResponders objectAtIndex:idx];
        [resp callWithArrayOfArgs:self.popupArguments];
}

Extracting your specific token from the message is just name+. This example is using (void) but it should work just fine - you aren't using the "no such method" path, you are just binding the method really late in the compile/link/run process...


Jeff Laing
 

This capability of Objective-C, to create classes on the fly, is one of the primo reasons why I can't understand people's fascination with Swift. Even C# can do this sort of thing, but people these days seem to be terrified of taking complete control.

Personally, I would be avoiding turning something into an NSString until the last minute. You could strcmp() the selector name against your fail pattern and just create your string from "selName+offset" rather than the more expensive substringFromIndex. Not quite sure why you need to change the case of the table but that's your grammar, I guess.

Nevertheless, don't waste time optimising till it's a known performance hit.

If this were being called millions of times, I would be building a static CFDictionary(), keyed by _cmd values I had previously encountered and storing their corresponding "snakeCased substrings" so that I only did that construction once. Or I would be asking myself "could stepDictForTableName: take a char* instead of an NSString*, etc. Again, CFDictionary is so much better than NSDictionary in that space. But that's me, I hate wasting cycles.

Good luck with it.


Jeff Laing
 

On review, one thing. Don't do this:

if ( [self respondsToSelector:sel] == NO )

It's a boolean method, never use an equality check for "true" or "false" on a boolean method, even if it seems to work, it sets you up for pain when you switch languages.


Sandor Szatmari
 

Jeff,

On Jul 22, 2020, at 17:44, Jeff Laing <jefflaing@...> wrote:



This capability of Objective-C, to create classes on the fly, is one of the primo reasons why I can't understand people's fascination with Swift.

Couldn’t agree more…

Even C# can do this sort of thing, but people these days seem to be terrified of taking complete control.

Personally, I would be avoiding turning something into an NSString until the last minute. You could strcmp() the selector name against your fail pattern and just create your string from "selName+offset" rather than the more expensive substringFromIndex. Not quite sure why you need to change the case of the table but that's your grammar, I guess.

There is no need to optimize for performance here…  higher level Obj-c interfaces are preferable.

Nevertheless, don't waste time optimising till it's a known performance hit.

If this were being called millions of times, I would be building a static CFDictionary(), keyed by _cmd values I had previously encountered and storing their corresponding "snakeCased substrings" so that I only did that construction once. Or I would be asking myself "could stepDictForTableName: take a char* instead of an NSString*, etc. Again, CFDictionary is so much better than NSDictionary in that space. But that's me, I hate wasting cycles.

Yes, lots of efficiencies can be made.  Unfortunately, it’s just not a necessity for us.

Thanks,
Sandor

Good luck with it.


Sandor Szatmari
 

Jeff,

On Jul 22, 2020, at 17:48, Jeff Laing <jefflaing@...> wrote:



On review, one thing. Don't do this:

if ( [self respondsToSelector:sel] == NO )

It's a boolean method, never use an equality check for "true" or "false" on a boolean method, even if it seems to work, it sets you up for pain when you switch languages.

Switch languages!!! Noooo…


robmartin@frontiernet.net
 

I learned a lot from this thread - thanks!