SwiftUI 大师之路 之 01 不要写if语句

所有 iOS 开发人员都编写(或遇到过)千行视图控制器。很难推理,很难添加新功能,而且容易出错。很明显,它试图做的太多了——但是如何在它发生之前阻止这种混乱呢?

一条规则:不要写 if 语句。

每个if语句增加了一个额外的分支,与前任牛逼试图读取代码时的复杂性RA水平。更广泛地说,它们暗示了开始形成的坏模式:这个函数试图做两种不同的事情,这取决于输入。在它失控之前,问问自己为什么要尝试这样写。是吗:

捕捉错误

需要 if 语句的最简单原因是进行错误或条件检查:确保输入在指定范围内。你会看到这样的代码:

// DON'T
func playVideo()
  if video.url == nil {
  } else {
    /* your code here */
  }

相反,使用guard语句和提前返回,这将大大提高代码的可读性。在你的函数开始时,你可以只保护可接受的输入——然后函数的其余部分变得干净,因为它只需要处理快乐路径。

// DO!
func playVideo() {
  guard video.url != nil else { return }
  /* your code here */
}

当您发现自己根据某些计算检查了函数体中的更多错误时,这是​​分解函数以再次使用保护模式的另一个提示。
甚至if let安全解包可空变量的模式也可以通过使用guard let来更好地提供服务,并在某些内容意外为空时提前返回和错误检查。

以不同的方式布局 UI

有条件地布局 UI 是 iOS 开发中最大的危险信号之一,也是 UI 错误的一个巨大来源。考虑以下:

// DON'T
class UserProfilePictureViewController {
override func viewDidLayoutSubviews() {
  super.viewDidLayoutSubviews()
  if (isUserActive) {
    /* layout user profile */
  } else {
    /* layout */
  }
}

使用标志进行布局会给您的代码增加指数级的复杂性,并导致功能意外闪烁的错误。添加新功能也变得更加困难,因为您必须考虑每个标志的两面,并确保不会意外破坏依赖标志的东西。最后,它会导致巨大的代码膨胀:两个非常不同的布局逻辑彼此相邻,这使得浏览代码具有挑战性。
相反,将功能分解为子视图。layoutSubview您应该根据功能拥有两个不同的视图,而不是在 中切换。当模式改变时,视图也应该改变。

管理状态

通常,您需要在视图控制器中使用标志来确定状态。如果用户已登录,则做一件事,否则做另一件事。然而,一旦你有两个标志,这很快就会崩溃:每个分支都需要担心每个额外的标志!复杂度成二次方增加。

// DON'T!
let label = UILabel()
if (isInEditor) {
  label.text = "Edit your Photo"
} else {
  label.text = "Publish your Photo"
}

您可以创建一个状态数据模型,而不是检查标志并打开它。使用enum然后在其中设置变量,具体取决于用户活动的状态。

// DO!
enum PhotoEditingState {
    case editor
    case publish

    var title : String {
        get {
            switch self {
            case .editor:
                return "Edit your Photo"
            case .publish:
                return "Publish your Photo"
            }
        }
    }
}

现在if,您可以将功能差异抽象到模型中,而不是在视图控制器中添加语句。当逻辑包含在数据模型中时,逻辑推理要容易得多。
更好的是,这种模式产生了超级可读的代码。在视图控制器内部,您可以简单地询问数据模型问题:

let label = UILabel()
label.text = state.title 

最后,这种模式很容易扩展。如果您在照片编辑流程中添加了新屏幕,则只需在内纳姆中添加一个新案例并填写所有变量 – 编译器甚至会确保您正在处理所有案例!如果添加需要在状态上更改的新按钮,则它就像在状态模型中添加新变量一样简单,并且编译器将再次确保您已为每个可能的状态填写了该按钮。

其他合法理由?

像任何好的规则一样,这个规则也是被打破的。时间轴和截止日期将使得将一个功能粘在现有功能上更具吸引力,有时它可能是当下正确的决定。但它总是会降低代码的质量。


精品教程推荐


加入我们一起学习SwiftUI

QQ:3365059189
SwiftUI技术交流QQ群:518696470
教程网站:www.openswiftui.com

发表回复