Swift 使用函数中指定的守卫和致命错误

Swift using guard and fatal error specified in an function

我使用枚举构建我的 UITableView 单元格:

  enum VAXSections: Int
  {
    case Segmented = 0
    case Scrollable = 1
    case ScheduledMode = 2
    case ScheduledFooter = 3
    case SilentHours = 4
    case SilentFooter = 5
  }

这里是我的使用方法:

  func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
  {
    guard let unwrappedSection = VAXSections(rawValue: indexPath.section) else {
      showFatalError()
      return nil
    }

这里没有什么问题我想保护我的节值,如果它在我的枚举中超出最大大小写。例如,如果 indexPath.section 大于 5,那么应用程序应该回退。但是如果你看到我们不能在这里 return nil,因为 cellForRowAtIndexPath 在任何情况下都必须 return 单元格。

我可以通过将 showFatalError() 小说替换为以下内容来提供更多可读性来解决问题:

    guard let unwrappedSection = VAXSections(rawValue: indexPath.section) else {
      fatalError("Check \(String(VAXUnitDashboardViewController.self)) UITableView datasource or check \(String(VAXSections.self)) enum.")
    }

那么我不需要 return 任何值。但后来我又遇到了另一个问题。因为我需要为我的 UITableView 指定至少 3 个数据源函数,所以我需要复制致命错误,我希望将其替换为一个始终执行相同操作的函数:

fatalError("Check \(String(VAXUnitDashboardViewController.self)) UITableView datasource or check \(String(VAXSections.self)) enum.")

我认为您实际上不需要在 3 个地方安装它。假设您正在谈论的 3 种数据源方法是:

func numberOfSectionsInTableView(_ tableView: UITableView) -> Int
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
func tableView(_ tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell

实际上,您只需要在其中之一上进行保护。

  1. numberOfSectionsInTableView 是第一个调用的方法,所以如果你在这里失败,其他两个方法将不会被调用。如果部分的数量是基于一些计算的,你也可以截断这个值,像这样:if calculatedNumberOfSections > 6 { return 6 } else { return calculatedNumberOfSections }(记住部分编号是基于0
  2. numberOfRowsInSection - 如果你在这里守卫,你有两个选择 - 要么以 fatalError 失败,要么(我认为更好)- return 0 如果部分编号高于 5 则通过。返回 0 将导致 cellForRowAtIndexPath 不被该部分调用。
  3. cellForRowAtIndexPath - 你已经知道了:)
enum VAXItems: String {
    case Item1
    case Item2
    case Item3
}

enum VAXSections: String {
    case Segmented
    case Scrollable
    case ScheduledMode
    case ScheduledFooter
    case SilentHours
    case SilentFooter
}

struct VAXModel {
    var type: VAXSections
    var items: [VAXItems]
}

然后在您的 UIViewController 上您可以拥有:

class ViewController: UIViewController {

    private var model: [VAXModel] = []

    override func viewDidLoad() {
        super.viewDidLoad()

        model = [
            VAXModel(type: .ScheduledMode, items: [.Item1, .Item2, .Item3]),
            VAXModel(type: .SilentFooter, items: [.Item1])
        ]

    }

    func numberOfSectionsInTableView(tableView: UITableView) -> Int {
        return model.count
    }

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

    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCellWithIdentifier(String(UITableViewCell), forIndexPath: indexPath)

        let item = model[indexPath.section].items[indexPath.row]

        switch item {
        case .Item1: cell.textLabel?.text = item.rawValue
        case .Item2: // Config
        case .Item3: // Config
        }

        return cell
    }

}