Forum Archive

Assigning action to UIBarButtonItem with objc_util

mcriley821

So I’m working on a ui with the ui module and the objc_util module. I needed to use the objc_util to do some user QOL improvements with the TextViews. This got me on wanting to continue improvements, and I’ve added a UIToolbar to the keyboard to allow the user to end editing the TextView with a UIBarButtonItem. But the problem is I also want to add another UIBarButtonItem that will clear all the text in the TextView, but I’m having trouble making this happen. There is no method in the TextView to just clear the text, and when init-ing the button to target the TextView and assigning the action to setText of the TextView I can’t figure out how to pass a empty string parameter. Here's an example of the gist of my problem:

import ui
from objc_util import *

view=ui.View()
textview=ui.TextView()
textview.text="hello" #make text to see if the button works
tvobj=ObjCInstance(textview)

#tried passing below as argument in button action
text=ObjCClass("NSMutableString").alloc().initWithString_('')

#below creates the button and assigns the target and action
#can't figure out how to pass argument as well.
#tried saying "setText:", 'setText:@""','setText=text'
btn=ObjCClass('UIBarButtonItem').alloc().initWithBarButtonSystemItem_target_action_(13,textview,'???') 
#the 13 is just the refresh button

#below finishes setting up the view and adding the button to the 
#keyboard toolbar
bar=ObjCClass('UIToolbar').alloc().init()
bar.sizeToFit()
keyboard=ObjCClass('UIKeyboard').alloc().init()
flex=ObjCClass('UIBarButtonItem').alloc().initWithBarButtonSystemItem_target_action_(5,None,None)
bar.items=[flex,btn]
textview.inputAccessoryView=bar
view.add_subview(textview)
view.present()

mikael

@mcriley821, see below for a function that creates a button that has the given label and calls the given function when clicked.

It uses an UI button as an intermediary. You have to retain a reference to this button to avoid crashes. Consider this a quick fix to move on with your coding - others may point to a way of making the call without extra ui.Button.

    def create_button(label, func):
        button_width = 25
        black = ObjCClass('UIColor').alloc().initWithWhite_alpha_(0.0, 1.0)
        action_button = ui.Button()
        action_button.action = func
        accessory_button = ObjCClass('UIBarButtonItem').alloc().initWithTitle_style_target_action_(label, 0, action_button, sel('invokeAction:'))
        accessory_button.width = button_width
        accessory_button.tintColor = black

        return (action_button, accessory_button)
mikael

@mcriley821, see here for the version without ui.Button. Not much different as you need to create an object with a method anyway.

mcriley821

@mikael Thanks for the help, I’ll try the intermediary ui button, but I’ve already tried the code in the other post. The problem with the other code (I think) is that I have a target, it just doesn’t have the method I want (clear text) so creating a new class doesn’t work for me. And even so in creating a new class, I would still need to find a way to target the TextView with my own method.

cvp

@mcriley821 could you try (see clear button at right)

from objc_util import *
import ui

UIBarButtonItem = ObjCClass('UIBarButtonItem')
UIBarButtonItemGroup = ObjCClass('UIBarButtonItemGroup')

def btnAction(_self, _cmd):
    tv = ObjCClass('UIApplication').sharedApplication().keyWindow().firstResponder()
    tv.setText_('')

ActionTarget = create_objc_class('ActionTarget', methods=[btnAction])
target = ActionTarget.new().autorelease()

@on_main_thread
def main():
    tv = ui.TextView(frame=(0, 0, 320, 320))
    b1 = UIBarButtonItem.alloc().initWithTitle_style_target_action_('clear', 0, target, 'btnAction').autorelease()
    group = UIBarButtonItemGroup.alloc().initWithBarButtonItems_representativeItem_([b1], None).autorelease()
    ObjCInstance(tv).inputAssistantItem().trailingBarButtonGroups = [group]
    tv.present('sheet')

if __name__ == '__main__':
    main()
mcriley821

@cvp I tried your code, but there’s no button that appears. Was it meant to be a fully-standalone test?

cvp

@mcriley821 you have to put the cursor in the TextView

mcriley821

@cvp I’m on iPhone, but I modified your code a little and it works! Thank you much for your help!

cvp

@mcriley821 Ok, sorry, I Always forget that I work iPad and most of other people work on iPhone