Swift : anyone have a better way?

I am creating a developement system that supports individual controls as well as control arrays (similar to a control set, but its really an array)

Part of what needs to be generated is a “dispatch” routine to handle any given event

Right now they look something like this (and this does work)

override func eventNAME(_ ctrl: NSResponder, arg : String ) { 
      switch ctrl {
         case ctrl_A    :  ctrl_A _eventNAME(arg)
         case ctrl_B[0] :  ctrl_b_eventNAME(0,arg)
         case ctrl_B[1] :  ctrl_b_eventNAME(1,arg)
         case ctrl_B[2] :  ctrl_b_eventNAME(2,arg)
         case ctrl_B[3] :  ctrl_b_eventNAME(3,arg)
         case ctrl_B[4] :  ctrl_b_eventNAME(4,arg)
         case ctrl_C    :  ctrl_C _eventNAME(arg)
         default : break 
      }
   }

ctrl_A, ctrl_B, and ctrl_C are all DIFFERENT object types [NSButton, NSSwitch etc]. but because they all inherit from NSResponder, their “pointer” allows this to work

in this example, ctrl_B is an ARRAY … there could be 100 instances not just the 5 in this example, there also could be dozens of arrays of other controls.

Can anyone think of a logic structure that would allow the same results as above, but without an ever increasing “Switch” statement?

I don’t know anything about Swift, so don’t know if this is possible, but logically I would test if a control was an array and if so, loop through it instead of listing each element out like you’re doing.

Or better yet, is there a way to loop through all controls on the current form/window, testing them against the passed control?

a jump table :slight_smile:
no loops, no figuring indexes, no nothing

the table has the control (or some unique id from the control etc) as the KEY and the VALUE is the method to call (possibly a delegate with one of 2 possible signatures)

in pseudo code

override func eventNAME(_ ctrl: NSResponder, arg : String ) { 

        //  if jump_table.haskey(ctrl) then
            //   if jump_table.lookup(ctrl) isa one_param_delegate then
                   // call the ones that JUST gets passed the control
                   // ie. ctrl_A _eventNAME(arg)
            //   else if jump_table.lookup(ctrl) isa two_param_delegate then
                   // call the ones that gets passed the index & control
                   // ie. ctrl_b_eventNAME(3,arg)                   
           // end if
       // else
           // uh something wrong if a control is NOT in our table !!!!!
       //

      }
   }

setting up the table happens at window construction/open time & also IF you permit controls to be added dynamically you need to add them to the jump table as well
if you permit removing them at runtime then also remove them from the jump table

now this handles a SINGLE event

you may nee d a wider table with more ways to tell which event to call etc
so you can have multiple events in the jump table

Thanks… all the suggestions lead me in a direction that I think will work out well
Each window will have a custom generated function that will return a “baseControl” and an index
If the control is NOT in a control array, it returns that control, and -1
otherwise it returns the first control in that array and the index of the actual control in the array.
Since the Switch statement mentioned in the first topic only cares about a base control, this works

 private func getBaseCtrl(ctrl:NSResponder) -> (NSResponder,Int) {
      switch ctrl {
         case GroupBox1 : return (GroupBox1,-1)
         case PBOTHER : return (PBOTHER,-1)
         case PB_in_BOX : return (PB_in_BOX,-1)
         default : break
      }
      if let _dsPUSHBUTTON = ctrl as? dsPUSHBUTTON? {
         if let indx=PB.firstIndex(of: _dsPUSHBUTTON!) {
            return (PB[0],indx)
         }
         if let indx=PBX.firstIndex(of: _dsPUSHBUTTON!) {
            return (PBX[0],indx)
         }
      }
   }

the the switch statment becomes

(baseCtrl,indx) = getBaseCtrl(ctrl)

switch baseCtrl {
case ctrl_B[0] : ctrl_b_eventNAME(indx,arg)
}

1 Like