ios 表格视图单元格中的 UIButton 操作
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/28894765/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
UIButton action in table view cell
提问by Sammmmm
I am trying to run an action for a button being pressed within a table view cell. The following code is in my table view controller class.
我正在尝试为在表视图单元格内按下的按钮运行一个操作。以下代码在我的表视图控制器类中。
The button has been described as "yes" in an outlet in my class of UITableViewCell called requestsCell.
在我的 UITableViewCell 类中名为 requestsCell 的插座中,该按钮被描述为“是”。
I am using Parse to save data and would like to update an object when the button is pressed. My objectIds array works fine, the cell.yes.tag also prints the correct number to the logs, however, I cannot get that number into my "connected" function in order to run my query properly.
我正在使用 Parse 来保存数据,并希望在按下按钮时更新一个对象。我的 objectIds 数组工作正常,cell.yes.tag 也将正确的数字打印到日志中,但是,我无法将该数字输入到我的“连接”函数中,以便正确运行我的查询。
I need a way to get the indexPath.row of the cell to find the proper objectId.
我需要一种方法来获取单元格的 indexPath.row 以找到正确的 objectId。
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as requestsCell
// Configure the cell...
cell.name.text = requested[indexPath.row]
imageFiles[indexPath.row].getDataInBackgroundWithBlock{
(imageData: NSData!, error: NSError!) -> Void in
if error == nil {
let image = UIImage(data: imageData)
cell.userImage.image = image
}else{
println("not working")
}
}
cell.yes.tag = indexPath.row
cell.yes.targetForAction("connected", withSender: self)
println(cell.yes.tag)
return cell
}
func connected(sender: UIButton!) {
var query = PFQuery(className:"Contacts")
query.getObjectInBackgroundWithId(objectIDs[sender.tag]) {
(gameScore: PFObject!, error: NSError!) -> Void in
if error != nil {
NSLog("%@", error)
} else {
gameScore["connected"] = "yes"
gameScore.save()
}
}
}
回答by IxPaka
Swift 4 & Swift 5:
斯威夫特 4 和斯威夫特 5:
You need to add target for that button.
您需要为该按钮添加目标。
myButton.addTarget(self, action: #selector(connected(sender:)), for: .touchUpInside)
And of course you need to set tag of that button since you are using it.
当然,您需要设置该按钮的标签,因为您正在使用它。
myButton.tag = indexPath.row
You can achieve this by subclassing UITableViewCell. Use it in interface builder, drop a button on that cell, connect it via outlet and there you go.
您可以通过继承 UITableViewCell 来实现这一点。在界面生成器中使用它,在该单元格上放一个按钮,通过插座连接它,然后就可以了。
To get the tag in the connected function:
要在连接的函数中获取标签:
@objc func connected(sender: UIButton){
let buttonTag = sender.tag
}
回答by Benedikt Reichert
The accepted answer using button.tag
as information carrier which button has actually been pressed is solid and widely accepted but rather limited since a tag can only hold Int
s.
使用button.tag
实际按下按钮作为信息载体的公认答案是可靠且广泛接受的,但相当有限,因为标签只能容纳Int
s。
You can make use of Swift's awesome closure-capabilities to have greater flexibility and cleaner code.
您可以利用 Swift 令人敬畏的闭包功能来获得更大的灵活性和更清晰的代码。
I recommend this article: How to properly do buttons in table view cells using Swift closuresby Jure Zove.
我推荐这篇文章:如何使用Jure Zove 的Swift 闭包在表格视图单元格中正确执行按钮。
Applied to your problem:
应用于您的问题:
Declare a variable that can hold a closure in your tableview celllike
var buttonTappedAction : ((UITableViewCell) -> Void)?
Add an action when the button is pressed that only executes the closure. You did it programmatically with
cell.yes.targetForAction("connected", withSender: self)
but I would prefer an@IBAction
outlet :-)@IBAction func buttonTap(sender: AnyObject) { tapAction?(self) }
- Now pass the content of
func connected(sender: UIButton!) { ... }
as a closure tocell.tapAction = {<closure content here...>}
. Please refer to the article for a more precise explanation and please don't forget to break reference cycles when capturing variables from the environment.
声明一个可以在 tableview单元格中保存闭包的变量,例如
var buttonTappedAction : ((UITableViewCell) -> Void)?
按下按钮时添加一个仅执行闭包的动作。你以编程方式做到了,
cell.yes.targetForAction("connected", withSender: self)
但我更喜欢一个@IBAction
插座:-)@IBAction func buttonTap(sender: AnyObject) { tapAction?(self) }
- 现在将 的内容
func connected(sender: UIButton!) { ... }
作为闭包传递给cell.tapAction = {<closure content here...>}
。请参阅文章以获得更精确的解释,并且在从环境中捕获变量时请不要忘记打破引用循环。
回答by kalpesh
Simple and easy way to detect button event and perform some action
检测按钮事件并执行某些操作的简单方法
class youCell: UITableViewCell
{
var yourobj : (() -> Void)? = nil
//You can pass any kind data also.
//var user: ((String?) -> Void)? = nil
override func awakeFromNib()
{
super.awakeFromNib()
}
@IBAction func btnAction(sender: UIButton)
{
if let btnAction = self.yourobj
{
btnAction()
// user!("pass string")
}
}
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
let cell = youtableview.dequeueReusableCellWithIdentifier(identifier) as? youCell
cell?.selectionStyle = UITableViewCellSelectionStyle.None
cell!. yourobj =
{
//Do whatever you want to do when the button is tapped here
self.view.addSubview(self.someotherView)
}
cell.user = { string in
print(string)
}
return cell
}
回答by levin varghese
We can create a closure for the button and use that in cellForRowAtIndexPath
我们可以为按钮创建一个闭包并在 cellForRowAtIndexPath 中使用它
class ClosureSleeve {
let closure: () -> ()
init(attachTo: AnyObject, closure: @escaping () -> ()) {
self.closure = closure
objc_setAssociatedObject(attachTo, "[\(arc4random())]", self,.OBJC_ASSOCIATION_RETAIN)
}
@objc func invoke() {
closure()
}
}
extension UIControl {
func addAction(for controlEvents: UIControlEvents = .primaryActionTriggered, action: @escaping () -> ()) {
let sleeve = ClosureSleeve(attachTo: self, closure: action)
addTarget(sleeve, action: #selector(ClosureSleeve.invoke), for: controlEvents)
}
}
And then in cellForRowAtIndexPath
然后在 cellForRowAtIndexPath
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
let cell = youtableview.dequeueReusableCellWithIdentifier(identifier) as? youCell
cell?.selectionStyle = UITableViewCell.SelectionStyle.none//swift 4 style
button.addAction {
//Do whatever you want to do when the button is tapped here
print("button pressed")
}
return cell
}
回答by Biswajit Banik
class TableViewCell: UITableViewCell {
@IBOutlet weak var oneButton: UIButton!
@IBOutlet weak var twoButton: UIButton!
}
class TableViewController: UITableViewController {
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! TableViewCell
cell.oneButton.addTarget(self, action: #selector(TableViewController.oneTapped(_:)), for: .touchUpInside)
cell.twoButton.addTarget(self, action: #selector(TableViewController.twoTapped(_:)), for: .touchUpInside)
return cell
}
func oneTapped(_ sender: Any?) {
print("Tapped")
}
func twoTapped(_ sender: Any?) {
print("Tapped")
}
}
回答by swiftBoy
With Swift 5this is what, worked for me!!
使用Swift 5,这对我有用!!
Step 1. Created IBOutlet for UIButton in My CustomCell.swift
步骤 1. 在 My CustomCell.swift 中为 UIButton 创建 IBOutlet
class ListProductCell: UITableViewCell {
@IBOutlet weak var productMapButton: UIButton!
//todo
}
Step 2. Added action method in CellForRowAtIndex method and provided method implementation in the same view controller
步骤 2. 在 CellForRowAtIndex 方法中添加 action 方法并在同一视图控制器中提供方法实现
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "ListProductCell") as! ListProductCell
cell.productMapButton.addTarget(self, action: #selector(ListViewController.onClickedMapButton(_:)), for: .touchUpInside)
return cell
}
@objc func onClickedMapButton(_ sender: Any?) {
print("Tapped")
}
回答by Huy Nghia
As Apple DOC
作为苹果文档
targetForAction:withSender:
Returns the target object that responds to an action.
targetForAction:withSender:
返回响应动作的目标对象。
You can't use that method to set target for UIButton
.
Try
addTarget(_:action:forControlEvents:)method
您不能使用该方法为UIButton
.
尝试
addTarget(_:action:forControlEvents:)方法
回答by Ammar Mujeeb
The accepted answer is good and simple approach but have limitation of information it can hold with tag. As sometime more information needed.
接受的答案是好的和简单的方法,但它可以用标签保存的信息有限。有时需要更多信息。
You can create a custom button and add properties as many as you like they will hold info you wanna pass:
您可以创建一个自定义按钮并添加任意数量的属性,它们将包含您想要传递的信息:
class CustomButton: UIButton {
var orderNo = -1
var clientCreatedDate = Date(timeIntervalSince1970: 1)
}
Make button of this type in Storyboard or programmatically:
在 Storyboard 中或以编程方式制作这种类型的按钮:
protocol OrderStatusDelegate: class {
func orderStatusUpdated(orderNo: Int, createdDate: Date)
}
class OrdersCell: UITableViewCell {
@IBOutlet weak var btnBottom: CustomButton!
weak var delegate: OrderStatusDelegate?
}
While configuring the cell add values to these properties:
在配置单元格时,向这些属性添加值:
func configureCell(order: OrderRealm, index: Int) {
btnBottom.orderNo = Int(order.orderNo)
btnBottom.clientCreatedDate = order.clientCreatedDate
}
When tapped access those properties in button's action (within cell's subclass) that can be sent through delegate:
当点击访问可以通过委托发送的按钮操作(在单元格的子类中)中的那些属性时:
@IBAction func btnBumpTapped(_ sender: Any) {
if let button = sender as? CustomButton {
let orderNo = button.orderNo
let createdDate = button.clientCreatedDate
delegate?.orderStatusUpdated(orderNo: orderNo, createdDate: createdDate)
}
}
回答by m azizi
in Swift 4
在斯威夫特 4
in cellForRowAt indexPath:
在 cellForRowAt 索引路径中:
cell.prescriptionButton.addTarget(self, action: Selector("onClicked:"), for: .touchUpInside)
function that run after user pressed button:
用户按下按钮后运行的功能:
@objc func onClicked(sender: UIButton){
let tag = sender.tag
}