こんにちは、ショッピングカート機能を処理する3つのボタン、プラス、マイナス、および削除ボタンを持つカスタムUITableViewCellがあり、どのセルがタッチされたかを知る必要があります。
「タグソリューション」を使用しようとしましたが、セルのライフサイクルが原因で機能しません。
誰かが解決策を見つけるのを手伝ってくれますか?
前もって感謝します
UITableViewCellのサブクラス内のセルデリゲートメソッドを使用してこれを解決していました。
簡単な概要:
1)プロトコルの作成
protocol YourCellDelegate : class {
func didPressButton(_ tag: Int)
}
2)サブクラス your UITableViewCell
(まだ行っていない場合):
class YourCell : UITableViewCell
{
var cellDelegate: YourCellDelegate?
@IBOutlet weak var btn: UIButton!
// connect the button from your cell with this method
@IBAction func buttonPressed(_ sender: UIButton) {
cellDelegate?.didPressButton(sender.tag)
}
...
}
)Letビューcontroller上記で実装されたYourCellDelegate
プロトコルに準拠。
class YourViewController: ..., YourCellDelegate { ... }
4)デリゲートを設定、セルが定義された後(再利用のため)。
let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier, for: indexPath) as! YourCell
cell.cellDelegate = self
cell.btn.tag = indexPath.row
5)同じコントローラ(実装されているUITableViewデリゲート/データソースはどこにありますか)、YourCellDelegate
プロトコルからメソッドを置く。
func didPressButton(_ tag: Int) {
print("I have pressed a button with a tag: \(tag)")
}
これで、ソリューションはタグ/番号に依存しなくなりました。必要な数のボタンを追加できるため、インストールするボタンの数に関係なく、デリゲート経由で応答を受け取る準備ができています。
このプロトコルデリゲートソリューションはiOSロジックで優先され、UISwitch
、UIStepper
などのテーブルセル内の他の要素に使用できます。
コミュニティから広く提案されているように、IBOutletsをプライベートにした後、同じ問題に遭遇しました。
私の解決策は次のとおりです。
<セルクラス内>
protocol YourCellDelegate: class {
func didTapButton(_ sender: UIButton)
}
class YourCell: UITableViewCell {
weak var delegate: YourCellDelegate?
@IBAction func buttonTapped(_ sender: UIButton) {
delegate?.didTapButton(sender)
}
}
<ViewControllerで>
class ViewController: UIViewController, YourCellDelegate {
func didTapButton(_ sender: UIButton) {
if let indexPath = getCurrentCellIndexPath(sender) {
item = items[indexPath.row]
}
}
func getCurrentCellIndexPath(_ sender: UIButton) -> IndexPath? {
let buttonPosition = sender.convert(CGPoint.zero, to: tableView)
if let indexPath: IndexPath = tableView.indexPathForRow(at: buttonPosition) {
return indexPath
}
return nil
}
}
Swift 4。*
それは次のようにもできます。多くのコーディングと委任は不要で、シンプルで簡単です。
cellForItemAt
の場合はUICollectionView
に、またはcellForRowAt
の場合はUITableView
に次のコードを配置します
cell.btn.tag = indexPath.row
cell.btn.addTarget(self, action: #selector(buttonSelected), for: .touchUpInside)
そして、あなたの方法は
@objc func buttonSelected(sender: UIButton){
print(sender.tag)
}
それで全部です。
@pedrouanは、ボタンのtag
オプションを使用する以外は素晴らしいです。多くの場合、tableViewCell
にボタンを設定すると、それらのボタンはtableView dataSourceを変更します(例:InsertRow、DeleteRow)。
ただし、新しいセルがinserted
またはdeleted
であっても、ボタンのタグは更新されません。したがって、ボタンのcell
をパラメーターに渡すのではなく、tag
自体をパラメーターとして渡すことをお勧めします。
これを実現するための例を次に示します。
あなたのExampleCell
protocol ExampleCellDelegate: class {
func didTapButton(cell: ExampleCell)
}
class ExampleCell: UITableViewCell {
weak var cellDelegate: ExampleCellDelegate?
@IBAction func btnTapped(_ sender: UIButton) {
cellDelegate?.didTapButton(cell: self)
}
}
あなたのViewController
class ViewController: ExampleCellDelegate {
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if let cell = tableView.dequeueReusableCell(withIdentifier: "ExampleCell", for: indexPath) as? ExampleCell {
cell.cellDelegate = self
return cell
}
return UITableViewCell()
}
func didTapButton(cell: ExampleCell) {
if let indexPath = tableView.indexPath(for: cell) {
// do Something
}
}
}
Swift 4.2
デリゲートの代わりにクロージャーを使用することもできます
1)UITableViewCellで:
class ExampleCell: UITableViewCell {
//create your closure here
var buttonPressed : (() -> ()) = {}
@IBAction func buttonAction(_ sender: UIButton) {
//Call your closure here
buttonPressed()
}
}
2)ViewControllerで
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "ExampleCell", for: indexPath) as! ExampleCell
cell.buttonPressed = {
//Code
}
return cell
}
}
TableViewCellビューの階層を使用して、選択したボタンのインデックスを取得することもできます。
次の手順を使用します。
tableviewのcellForRowAtIndexpathにセレクターを追加します。
btn?.addTarget(self, action:#selector(buttonPressed(_:)), for:.touchUpInside)
2。次のメソッドを使用してindexPathを取得します。
func buttonPressed(_ sender: AnyObject) {
let button = sender as? UIButton
let cell = button?.superview?.superview as? UITableViewCell
let indexPath = tblview.indexPath(for: cell!)
print(indexPath?.row)
}
TableviewセルのUIButton。プログラムでSwift 4.2のアクションメソッドを作成します
cell.btnlike.addTarget(self, action: #selector(buttonbtnlikePressed(_:event:)), for: .touchUpInside)
@objc func buttonbtnlikePressed(_ sender: Any, event: Any) {
let point : CGPoint = (sender as AnyObject).convert(CGPoint.zero, to:tblPost)
var indexPath = self.tblPost!.indexPathForRow(at: point)
if let btnlike = sender as? UIButton{
if btnlike.isSelected{
btnlike.isSelected = false
}else{
btnlike.isSelected = true
}
}
}