codeArtist codeArtist - 5 months ago 24
iOS Question

Assign 'action' dynamically in uibutton.addTarget

please bear with me, as I'm new to swift -4 weeks old-.

I've created the following 2 functions in fileA.swift

func custombttn(theSelector:Selector)-> UIButton{

let bttn = UIButton(frame: CGRect(x:20, y:400, width:200, height:30))
bttn.setTitle("tap this button", for: UIControlState.normal)
bttn.backgroundColor = UIColor.black
bttn.setTitleColor(UIColor.magenta, for: UIControlState.normal)
bttn.addTarget(bttn, action: theSelector, for: UIControlEvents.touchUpInside)

return bttn

}

func customtxtfld() -> UITextField{

let txtField = UITextField(frame: CGRect(x:20, y:360, width:200, height:30))

txtField.borderStyle = UITextBorderStyle.roundedRect
txtField.backgroundColor = UIColor.magenta
txtField.placeholder = "Do you like me now..?"

return txtField

}


The reason behind the
custombttn(theSelector:Selector)
, is that i want to pass the function dynamically to the button in my viewcontroller file.

Now, moving the fileB.swift, I have the following code...

class TabOneViewController: UIViewController{

let txt = customtxtfld()
let bttn = custombttn(theSelector: #selector(updatetxt))

override func loadView() {

super.loadView()

view.addSubview(txt)
view.addSubview(bttn)

}

func updatetxt(){

txt.text = "hello, you!"
}

}


Here is where things get tricky, when I attempt to build, I don't get any error (not even a warning). However, when I run the app, and tap the
bttn
in fileB.swift, I get the following error during runtime:


Terminating app due to uncaught exception
'NSInvalidArgumentException', reason: '-[UIButton updatetxt]:
unrecognized selector sent to instance 0x7f8453415670'


If I have 2 or more functions in my fileB.swift that I wish to assign dynamically to the action part of the addTarget, is there any way I can pass the selector dynamically to a button..?

Appreciate your time and assistance. Please let me know if I need to explain something further.

Answer Source

It's crashing because your button target is wrong.

func custombttn(target:Any, theSelector:Selector)-> UIButton{

    let bttn = UIButton(frame: CGRect(x:20, y:400, width:200, height:30))
    bttn.setTitle("tap this button", for: UIControlState.normal)
    bttn.backgroundColor = UIColor.black
    bttn.setTitleColor(UIColor.magenta, for: UIControlState.normal)
    bttn.addTarget(target, action: theSelector, for: UIControlEvents.touchUpInside)        
    return bttn        
}

And use it like this

class TabOneViewController: UIViewController{

    let txt = customtxtfld()

    override func loadView() {

        super.loadView()

            view.addSubview(txt)

            let bttn = custombttn(target:self,  theSelector: #selector(updatetxt))
            view.addSubview(bttn)

    }

     func updatetxt(){

        txt.text = "hello, you!"
    }

}