私はNiravに同意し、問題のセルのNSIndexPath
を判定するためにセルを使用することに同意します。
個人的には、セルをデータソースのサブクラスにして、ピッカーの委任を行い、ピッカーの責任を負わせたいと思います。これにより、どのピッカーがどのセルに関連付けられているかについての混乱が完全に排除されます。しかし、ユーザーがピッカーから値を選択し、ビューコントローラがモデルを更新できるときに、セルがビューコントローラに通知できるプロトコルがあります。
// CustomCell.swift
import UIKit
/// Protocol that the view controller will conform to in order to receive updates
/// from the cell regarding which row in the picker was picked.
///
/// - note: This is a `class` protocol so that I can use `weak` reference.
protocol CustomCellDelegate: class {
func cell(customCell: CustomCell, pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int)
}
/// Custom cell subclass, which is the picker's data source and delegate
class CustomCell: UITableViewCell, UIPickerViewDataSource, UIPickerViewDelegate {
/// The delegate who we will inform of any picker changes.
///
/// This is weak to avoid strong reference cycle.
weak var delegate: CustomCellDelegate?
/// The array of values to be shown in the picker.
///
/// If the `values` changes, this reloads the picker view.
var values: [String]? {
didSet {
pickerView.reloadComponent(0)
}
}
/// The outlet to the picker in the cell.
@IBOutlet weak var pickerView: UIPickerView!
// MARK: UIPickerViewDataSource
func numberOfComponentsInPickerView(pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return values?.count ?? 0
}
// MARK: UIPickerViewDelegate
func pickerView(pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
return values?[row] ?? ""
}
func pickerView(pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
delegate?.cell(self, pickerView: pickerView, didSelectRow: row, inComponent: component)
}
}
そしてビューコントローラ:
// ViewController.swift
import UIKit
class ViewController: UITableViewController, CustomCellDelegate {
// an array of arrays of acceptable values
let troupes = [
["Mo", "Larry", "Curly"],
["Abbott", "Costello"],
["Groucho", "Harpo", "Zeppo", "Chico", "Gummo"],
["Laurel", "Hardy"],
["Graham Chapman", "John Cleese", "Terry Gilliam", "Eric Idle", "Terry Jones", "Michael Palin"]
]
/// An array that indicates which is item is selected for each table view cell
var selectedItemForRow: [Int]!
override func viewDidLoad() {
super.viewDidLoad()
selectedItemForRow = troupes.map { _ in return 0 } // initialize the `selectedItemForRow` array with zeros
// Whatever further initialization of the view controller goes here.
}
// MARK: UITableViewDataSource
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return troupes.count
}
// Populate cell, setting delegate, list of acceptable values, and currently selected value.
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("CustomCell", forIndexPath: indexPath) as! CustomCell
cell.delegate = self
cell.values = troupes[indexPath.row]
cell.pickerView.selectRow(selectedItemForRow[indexPath.row], inComponent: 0, animated: false)
return cell
}
// MARK: CustomCellDelegate
// When the cell tells us that the user changed the selected row, let's update our model accordingly.
func cell(customCell: CustomCell, pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
if let indexPath = tableView.indexPathForCell(customCell) {
selectedItemForRow[indexPath.row] = row
}
}
}
[いいえ、 'tag'は本当に悪い識別目的 –
ごとに異なるタグを設定する必要が
たとえば、この
UITableViewCell
サブクラスを考えます細胞を追跡する方法とAppleは今日その習慣を失望させている。あなたは 'UITableViewCell'をサブクラス化し、ビューコントローラではなく、セルにプロパティを持たなければなりません。 – Robプロトタイプのセルは、その再利用識別子でデキューされたすべてのセルで同じUIPickerViewを再利用するという問題があるようです。これはAppleのドキュメンテーションと矛盾しているようですので、私はそれがバグだと仮定しなければなりません。ストーリーボードに4つのプロトタイプのセルを作成し、それぞれが異なる再利用された識別子を持つようにしてから、それぞれのセルを別の再利用識別子からデキューし、各ピッカーに異なるタグ付けを行いました。 (別の方法でタグを付けても同じ理由で動作しませんでした) –