如何在UITableView

时间:2016-07-28 04:51:01

标签: ios uitableview custom-controls reuseidentifier

我正在创建一个用于访问应用中设置的视图,该视图将显示在UITableView中。有些单元格会有一个UITableViewCellAccessoryDisclosureIndicator,我需要一个UISwitch,另一个单元格的UISegmentedControl类似:

enter image description here

换句话说,我想我需要自定义单元格。通过大量的研究,我已经非常接近,但我无法将我学到的所有东西连接在一起。这就是我所做的:

创建了三个UITableViewCell类:

class DisclosureCell: UITableViewCell {
  override func awakeFromNib() {
    super.awakeFromNib()
  }

  override func setSelected(selected: Bool, animated: Bool) {
    super.setSelected(selected, animated: animated)

    // Configure the view for the selected state
  }

  class func defaultIdentifier() -> String {
    return NSStringFromClass(self)
  }

}

class SegmentedControlCell: UITableViewCell {

  override func awakeFromNib() {
    super.awakeFromNib()
  }

  override func setSelected(selected: Bool, animated: Bool) {
    super.setSelected(selected, animated: animated)

    // Configure the view for the selected state
  }

 class func defaultIdentifier() -> String {
    return NSStringFromClass(self)
  }

}

class SwitchCell: UITableViewCell {

  override func awakeFromNib() {
    super.awakeFromNib()
  }

  override func setSelected(selected: Bool, animated: Bool) {
    super.setSelected(selected, animated: animated)

    // Configure the view for the selected state
  }

  class func defaultIdentifier() -> String {
    return NSStringFromClass(self)
  }

}

我有我的Sections类和Section结构,它将提供表视图部分和每个可用选项:

class SettingsData {

  func getSectionsFromData() -> [Section] {

  var settings = [Section]()

    let preferences = Section(title: "OPTIONS", objects: ["Formulas", "Lifts", "Units", "Allow 15 reps"])
    let patronFeatures = Section(title: "PATRON FEATURES", objects: ["Support OneRepMax"])
    let feedback = Section(title: "FEEDBACK", objects: ["Send Feedback", "Please Rate OneRepMax"])

    settings.append(preferences)
    settings.append(patronFeatures)
    settings.append(feedback)

    return settings
  }
}

struct Section {
  var sectionHeading: String
  var items: [String]

  init(title: String, objects: [String]) {
    sectionHeading = title
    items = objects

  }

}

最后,我的UITableViewController

class SettingsViewController: UITableViewController {

  override func viewDidLoad() {
    super.viewDidLoad()

    self.navigationController?.navigationBar.topItem?.title = "Settings"

    navigationItem.rightBarButtonItem = UIBarButtonItem(title: "Done", style: .Plain, target: self, action: #selector(self.dismissSettings(_:)))

  }

  func dismissSettings(sender: AnyObject?) {
    self.dismissViewControllerAnimated(true, completion: nil)

  }

  // MARK: - Table view data source

  var sections: [Section] = SettingsData().getSectionsFromData()

  override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
    return sections.count

  }

  override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return sections[section].items.count

  }

  override func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
    return sections[section].sectionHeading
  }

  override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCellWithIdentifier("DisclosureCell", forIndexPath: indexPath)
    cell.textLabel?.text = sections[indexPath.section].items[indexPath.row]

    return cell

  }

我认为我需要帮助的是:

  • 当我创建每个单元格时,如何确定每个单元格的三种类型中的哪一种,以便我可以根据类型显示它们以及正确地将每种类型出列
  • 我在每个自定义类中创建了func defaultIdentifier() -> String,并在Storyboard中为每个单元格类型指定了重用标识符。我需要同时做两件事吗?
  • 我是否需要注册这些单元格,或者这是不必要的,因为我正在使用故事板?

我发现了很多关于这个主题的帖子,但要么是在Objective-C中,要么他们没有说出我似乎被困在的特定部分。

谢谢!

更新

我已更新我的override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell,如下所示:

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    let cellIdentifier = tableView.cellForRowAtIndexPath(indexPath)?.reuseIdentifier
    if cellIdentifier == "DisclosureCell" {
      let cell: UITableViewCell = UITableViewCell(style: UITableViewCellStyle.Default, reuseIdentifier: "DisclosureCell")
      cell.textLabel?.text = sections[indexPath.section].items[indexPath.row]

      return cell

    } else if cellIdentifier == "SegmentedControlCell"  {
      let cell: UITableViewCell = UITableViewCell(style: UITableViewCellStyle.Default, reuseIdentifier: "SegmentedControlCell")
      cell.textLabel?.text = sections[indexPath.section].items[indexPath.row]

      return cell
    }
      else {
          let cell: UITableViewCell = UITableViewCell(style: UITableViewCellStyle.Default, reuseIdentifier: "SwitchCell")
          cell.textLabel?.text = sections[indexPath.section].items[indexPath.row]

      return cell
      }
  }

我希望这是朝着正确方向迈出的一步,但我仍然遗漏了一些东西,因为我收到了这个错误:

2016-07-28 07:15:35.894 One Rep Max [982:88043] 由于未捕获的异常“NSRangeException”而终止应用,原因如下: ' - [__ NSArrayI objectAtIndex:]:索引2超出界限[0 .. 0]'

我需要找出一种方法让每个单元格知道它应该是哪三种类型,然后根据它的类型,我可以在上面的代码中设置它。

更新2 我现在已经使用indexPath.row

进行了工作

enter image description here

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCellWithIdentifier("CustomTableViewCell", forIndexPath: indexPath) as! CustomTableViewCell
    if indexPath.row == 0 {
      cell.selectionStyle = .None
      cell.textLabel!.text = sections[indexPath.section].items[indexPath.row]
      cell.accessoryType = UITableViewCellAccessoryType.DisclosureIndicator
      return cell

    } else if indexPath.row == 1 {
      cell.selectionStyle = .None
      cell.textLabel!.text = sections[indexPath.section].items[indexPath.row]
      //cell.accessoryView = useAuthenticationSwitch
      let switchView: UISwitch = UISwitch()
      cell.accessoryView = switchView
      switchView.setOn(false, animated: false)
      return cell

    } else {
      cell.selectionStyle = .None
      cell.textLabel!.text = sections[indexPath.section].items[indexPath.row]
      let segmentedControl: UISegmentedControl = UISegmentedControl(items: ["lbs", "kg"])
      segmentedControl.selectedSegmentIndex = 0
      segmentedControl.addTarget(self, action: nil, forControlEvents: .ValueChanged)
      cell.accessoryView = segmentedControl
      return cell

    }
  }

问题是,使用indexPath.row时,并非所有行都具有正确的accessoryView。在上面的示例中,我希望前两行包含disclosureIndicators,第三行包含UISegmentedControl,第四行包含UISwitch。现在,我完全理解为什么我的代码产生了这个 - 这是因为accessoryView由单元格的位置决定。相反,我希望能够告诉每个单元格正在创建,“你是这个设置的单元格,所以你得到[填空] accessoryView”。我为每种类型创建了自定义单元格类,并试图做我正在尝试做的事情,但无法弄明白。您可能会注意到,在上面的代码中,我转到了一个自定义单元类并重用标识符。

我想我可以做if indexPath.row == 0 | 1 { blah, blah }之类的事情,但这种方法不会贯穿每个section。如果我尝试像这样处理每个section,那么代码将变得比现在更加混乱。必须有一个更聪明的方式。

有吗?

1 个答案:

答案 0 :(得分:0)

我建议你使用静态单元格(不是原型)来设置这样的屏幕。 您可以在故事板中更改单元格类型。 在将IBOutlets分配给所有控件并使它们与模型交互之后。