处理视图控制器状态

视图控制器除其他功能外,还负责在用户输入以及与基础数据进行交互之后更改视图状态。

您可以将视图状态视为输入和输出对。 每当用户选择一行时,视图控制器就会启用特定按钮。 当API开始获取新数据时,视图控制器将显示活动指示器。

映射这些状态的一种方法是使用布尔值,也称为标志 。 您有一个标志来说明当前状态是否为错误。 另一个告诉您内容是否正在加载。 彼此之间还有另外一种情况。

这种方法存在潜在的问题,您将看到其中的一些问题。 本文还显示了一种更好的状态处理方式。

每个州是一个不同的标志

检查以下代码以处理公共视图控制器的状态:

  var isLoading = false 
var产品:[产品] = []
var错误:错误?

在这种情况下,您有三种可能的状态:

  • 装货
  • 内容加载
  • 错误

考虑所有可能发生的相互作用。 这里是其中的一些:

  • 视图控制器使用API​​来获取内容。 然后将isLoading设置为true 。 并且由于它现在处于加载状态,因此它显示了活动指示器。
  • 它接收一些产品作为响应,并在表格视图中显示内容。 但是,如果响应是错误,则显示“重试”消息。
  • 用户拉表视图以刷新数据。 在这种情况下,视图控制器将再次调用API。

这是一个容易出错的代码,因为每当发生这些交互之一时,您都必须更新所有标志。 而且,即使您忘记了一个,您也可能陷入不确定的状态并产生错误。

接口上的状态通常是互斥的。 这就是为什么用标志处理状态会带来歧义的原因。 映射状态的更好方法是使用枚举。

用枚举处理状态

Swift中的枚举是强大的值类型,它们不仅可以定义一组相关的事物,还可以为每种不同的情况指定关联的值。

检查多选题应用的以下枚举映射状态:

 枚举状态{ 
案例未回答
案例回答(选项)
案例确认(选项)
}

这显示了一组明确定义的状态。 视图控制器没有很多标志,而是具有如下状态变量:

 类MCQViewController:UIViewController { 
var state:State = .notAnswered
}

这种方法有很多好处。 首先, 类型系统将确保正确设置状态。 这是一个示例,当用户选择一个选项时:

  let option = option(用于:indexPath) 
self.state = .answered(选项)

类型系统将不允许您设置模糊状态。

由于现在您更改视图控制器的状态,将值分配给单个变量,因此您可以受益于使用属性观察器作为更新接口的中心点。

例如,如果处于正确状态,则可以使用didSet启用confirmButton

  var state:State = .notAnswered { 
didSet {
切换状态{
案例.answered(_):
ConfirmButton.isEnabled = true

另一个很大的好处是您避免使用不必要的Optionals 。 您可能会使用var selected: Option? 如果在标志方法中。 并且您将有这样的事情:

 如果让selected = selected,则isRightAnswer(selected){ 
庆祝()
}

尽管if let语句没有任何问题, if let使用enum方法会使代码变得更简单:

 案例。已确认(选中): 
如果isRightAnswer(已选择){
庆祝()
}

结论

寻找机会简化代码,尤其是视图控制器。 您会发现,值类型的空间比普通的Model Layer还要大。

您还能考虑使用Enum处理视图控制器中的状态的其他好处吗? 缺点呢? 将您的想法放在下面的评论中。