Thom Thom - 3 months ago 16
Swift Question

Pass selector (function name) to function in swift

I want to pass the selector for a function to another function. Right now I'm just passing the string and doing several if statements. If I could pass the actual function selector to the function, I could eliminate all the if statements.

My current function:

func getBtn(i: String, f: String) -> UIBarButtonItem
{
let btn: UIButton = UIButton();
btn.frame=CGRectMake(0,0,30,30)
btn.setBackgroundImage(UIImage(named:i), forState: UIControlState.Normal)
if f == "funcOne"{ btn.addTarget(self, action: #selector(self.funcOne), forControlEvents:.TouchUpInside) }
else if f == "funcTwo"{ btn.addTarget(self, action: #selector(self.funcTwo), forControlEvents:.TouchUpInside) }
else if f == "funcThree"{ btn.addTarget(self, action: #selector(self.funcThree), forControlEvents:.TouchUpInside) }
else if f == "funcFour"{ btn.addTarget(self, action: #selector(self.funcFour), forControlEvents:.TouchUpInside) }
// etc.
let barBtn = UIBarButtonItem(customView: btn)
return barBtn;
}


Usage:

items.append(self.getBtn("checkmark",f:"funcOne"));


What I'd like to be able to do:

func getBtn(i: String, f: SOME_TYPE_OF_THING) -> UIBarButtonItem
{
let btn: UIButton = UIButton();
btn.frame=CGRectMake(0,0,30,30)
btn.setBackgroundImage(UIImage(named:i), forState: UIControlState.Normal)
btn.addTarget(self, action: #selector(f), forControlEvents:.TouchUpInside)
let barBtn = UIBarButtonItem(customView: btn)
return barBtn;
}


Usage:

items.append(self.getBtn("checkmark",f:self.funcOne));

Answer

The purpose of #selector() syntax is to save you from the possible error in having to write a selector as a literal string, which is error-prone. Nevertheless, you are free to write Selector(f) instead of using #selector() syntax.

However, it would be even better if f were itself typed as Selector:

func getBtn(i: String, f: Selector) -> UIBarButtonItem

That way, you could keep using #selector but do it in the call:

items.append(self.getBtn("checkmark",f:#selector(funcOne)))

In getBtn you would then just pass f directly as the button action.