テーブルビューセル内で押されているボタンのアクションを実行しようとしています。次のコードは、Table View Controllerクラスにあります。
ボタンは、requestsCellと呼ばれるUITableViewCellのクラスのアウトレットで「はい」と説明されています。
Parseを使用してデータを保存していますが、ボタンが押されたときにオブジェクトを更新したいと思います。 objectIds配列は正常に機能し、cell.yes.tagは正しい番号をログに出力しますが、クエリを適切に実行するために「接続された」関数にその番号を取得することはできません。
適切なobjectIdを見つけるために、セルのindexPath.rowを取得する方法が必要です。
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()
}
}
}
Swift 4&Swift 5:
そのボタンのターゲットを追加する必要があります。
myButton.addTarget(self, action: #selector(connected(sender:)), for: .touchUpInside)
そしてもちろん、ボタンを使用しているため、そのボタンのタグを設定する必要があります。
myButton.tag = indexPath.row
これを実現するには、UITableViewCellをサブクラス化します。インターフェースビルダーで使用し、そのセルにボタンをドロップし、アウトレット経由で接続すると、そこに行きます。
接続された関数でタグを取得するには:
@objc func connected(sender: UIButton){
let buttonTag = sender.tag
}
ボタンが実際に押された情報キャリアとしてbutton.tag
を使用した受け入れられた回答は堅実で広く受け入れられていますが、タグはInt
sのみを保持できるため、かなり制限されています。
Swiftの優れたクロージャー機能を利用して、柔軟性とコードをよりクリーンにすることができます。
この記事をお勧めします: Swiftクロージャーを使用してテーブルビューセルでボタンを適切に行う方法 by Jure Zove。
あなたの問題に適用:
テーブルビューでクロージャを保持できる変数を宣言しますcell
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...>}
に渡します。より正確な説明については記事を参照してください。また、環境から変数をキャプチャするときに参照サイクルを中断することを忘れないでください。ボタンイベントを検出して何らかのアクションを実行するシンプルで簡単な方法
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
}
ボタンのクロージャーを作成し、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)
}
}
そして、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
}
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")
}
}
As Apple DOC
targetForAction:withSender:
アクションに応答するターゲットオブジェクトを返します。
そのメソッドを使用してUIButton
のターゲットを設定することはできません。
Try addTarget(_:action:forControlEvents:) method
Swift 5で、これは私にとってはうまくいきました!!
手順1. My CustomCell.SwiftにUIButton用のIBOutletを作成しました
class ListProductCell: UITableViewCell {
@IBOutlet weak var productMapButton: UIButton!
//todo
}
手順2. CellForRowAtIndexメソッドにアクションメソッドを追加し、同じView Controllerにメソッド実装を提供
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")
}
Swift 4
cellForRowAt indexPathで:
cell.prescriptionButton.addTarget(self, action: Selector("onClicked:"), for: .touchUpInside)
ユーザーがボタンを押した後に実行される関数:
@objc func onClicked(sender: UIButton){
let tag = sender.tag
}