Try with the best use of swift closures : Simple, Quick & Easy.
In cellForRowAtIndexPath method:
let cell = tableView.dequeueReusableCell(withIdentifier: "CustomCellIdentifier", for: indexPath) as! CustomCell
cell.btnTick.mk_addTapHandler { (btn) in
     print("You can use here also directly : \(indexPath.row)")
     self.btnTapped(btn: btn, indexPath: indexPath)
}
Selector Method for external use out of cellForRowAtIndexPath method:
func btnTapped(btn:UIButton, indexPath:IndexPath) {
    print("IndexPath : \(indexPath.row)")
}
Extension for UIButton :
extension UIButton {
    private class Action {
        var action: (UIButton) -> Void
        init(action: @escaping (UIButton) -> Void) {
            self.action = action
        }
    }
    private struct AssociatedKeys {
        static var ActionTapped = "actionTapped"
    }
    private var tapAction: Action? {
        set { objc_setAssociatedObject(self, &AssociatedKeys.ActionTapped, newValue, .OBJC_ASSOCIATION_RETAIN) }
        get { return objc_getAssociatedObject(self, &AssociatedKeys.ActionTapped) as? Action }
    }
    @objc dynamic private func handleAction(_ recognizer: UIButton) {
        tapAction?.action(recognizer)
    }
    func mk_addTapHandler(action: @escaping (UIButton) -> Void) {
        self.addTarget(self, action: #selector(handleAction(_:)), for: .touchUpInside)
        tapAction = Action(action: action)
    }
}