Can we use UIAction on UIButton controls created with Codea’s ObjC bridge as handlers?

While awaiting delegate functionality in Codea’s ObjC bridge, I was wondering if it was currently possible to use the UIAction Class with UIButton as simple control handlers as suggested in this example from an online Swift tutorial:

class ViewController: UIViewController {
private let someActivity: SomeActivity

override func viewDidLoad() {
    let signUpAction = UIAction(
        title: "Sign Up",
        image: UIImage(systemName: "sign.up"),
        handler: { [someActivity] _ in
            someActivity.startAnimating()
        }
    )

    let signUpButton = UIButton(primaryAction: signUpAction)
    view.addSubview(signUpButton)
}

}

From what I understood, the “primaryAction” method for UIButton invokes the UIAction handler block whenever the UIButton is touched. That would seem an easy way to create simple GUI buttons in Codea with ObjC. However, I tried playing around with the above example to create a simple button and tried converting the above Swift code to Codea’s Objc format but couldn’t seem to format the handler block of code correctly to get UIButton to accept the handler in its primaryAction method (e.g. with signUpButton = UIButton:primaryAction_(signUpAction), signUpAction was considered an invalid argument).

Should UIAction be able to work as a handler for a UIButton in the latest Codea release? If so, can anyone provide a sample snipped of code that I could use to try out that functionality in my app? If not, I will look for other handler solutions and await an upcoming Codea release that supports delegates.

Thank you.

@jfperusse,

Now that Codea and objc seem to be working even better together, I’m exploring using objc bridge to give my projects some basic GUI functionality. I understand the basics of how to use UITextView and UILabel; would you mind at your convenience providing small snippet examples of how to use objc bridge with:

UIButton and
NSComboBox?

Thanks :blush:!

Creating the UIButton itself was not too difficult, but still not able to get the selector pattern of callback to work (crashes Codea each time I tap on the button).

   -- UI button (note: previously defined vc = objc.viewer)
   uiButton = objc.UIButton
   local frame = objc.rect(0,0,100,80)
   -- typedText is a text string printed out later in my program
   function vc:buttonTapped()
        typedText = "tapped"
   end
   local selector = objc.selector("buttonTapped")
   local testButton = uiButton:alloc():initWithFrame_(frame)
   -- event 64 = touched up inside button 
   testButton:addTarget_action_forControlEvents_(vc,selector,64)
   -- State "0" = non-clicked button
   testButton:setTitle_forState_(" Start/Stop Rotation ",0)
   testButton:setTitleColor_forState_(color(0,255,0),0)
   testButton:setBackgroundColor_(color(0,0,255))
   vc.view:addSubview_(testButton)
   -- code using Apple's custom layout functionality 
   testButton.translatesAutoresizingMaskIntoConstraints = false
   testButton.centerXAnchor:constraintEqualToAnchor_(vc.view.centerXAnchor).active = true
   testButton.topAnchor:constraintEqualToAnchor_constant_(vc.view.topAnchor, HEIGHT/2 - 80).active = true

I followed the reference example for using objc.selector but the actual implementation with a UIButton seems different enough than for the NotificationCenter that I can’t follow the reference’s example verbatim.

If I can figure out how to use the selector “action/target” pattern of Objective-C callbacks correctly in Codea, I’ll be able to start using Objective-C buttons in my projects. It looks like the NSComboBox uses the delegate pattern of callbacks which I do understand how to use with the Codea Objective-C bridge.

Any suggestions would be appreciated.

Thanks!

So, I got the UIButton to work with its callbacks by using one of the newer Objective-C callback patterns (which I believe is called the ‘closure’ method) that I found that @Steppers used in his UIKIt project. Here is the simplified code to create a button that responds to being clicked without formally designating a selector:

-- UIButtonTest

function setup()
    viewer.mode = FULLSCREEN
    --note: the next statement gets the actual UIViewController running in Codea
    local vc = objc.viewer
    local uiButton = objc.UIButton
    -- for test purposes will increment variable a as a counter and print in draw()
    local action = objc.UIAction:actionWithHandler_(function(objAction) a= a+1 end)
    local testButton = uiButton:buttonWithType_primaryAction_(objc.enum.UIButtonType.system, action)
    testButton:setTitle_forState_(" Increment Counter ", objc.enum.UIControlState.normal)
    testButton:setTitleColor_forState_(color(0,255,0), objc.enum.UIControlState.normal)
    testButton:setBackgroundColor_(color(0,0,255))
    vc.view:addSubview_(testButton)
    -- code using Apple's custom layout functionality 
    testButton.translatesAutoresizingMaskIntoConstraints = false
    testButton.centerXAnchor:constraintEqualToAnchor_(vc.view.centerXAnchor).active = true
    testButton.topAnchor:constraintEqualToAnchor_constant_(vc.view.topAnchor, HEIGHT/2 - 80).active = true
    a = 0
end

function draw()
    -- This sets a dark background color 
    background(40, 40, 50)
    text(tostring(a),WIDTH/2,400)  
end

There may though be something wrong with this code since, even with this simple UI button and no other code in the project, the program variably lags in carrying out the action specified for each button click. The button changing state doesn’t seem to lag (i.e. the button goes from having a title when not clicked to having no title when clicked as expected per the script) but (especially when first starting the program), multiple clicks don’t seem to generate any action (as seen by a failure to show an incremented value on variable a on screen).

The lag in responsiveness is even more apparent when I added this UIButton to my old ObjC demo project contains an ObjC TextView field, a Codea 3D Scene, an in-window Web Browser in addition to the UIButton (screenshot attached).

I hope this helps others who would like to make simple Objective C buttons for their projects and welcome input from the community on how the above code might be optimized to not variably lag on input. :blush:

Ah, reading more it looks like I probably should be using co-routines to modulate the execution of Objective-C commands and Codea lua commands like @Steppers did in his Codea+ library to make Objective-C parts of the code run smoother. I’ll read up more on how to do that.