TinyExperience:Inline function的使用场景

Galvin Li
6 min readJan 27, 2019

--

English version also available: TinyExperience: When to use inline function

Swift普通的function相信大家都已经用烂了,但inline function不一定每个人都有使用,本文就是介绍一下我使用inline function的常见场景。

什么是inline function

我们一般使用的function都是在class、struct、enum之类的层级:

class Example {
func method1() {}
}

而inline function则是在function层级下添加的function,像这样子:

class Example {
func method1() {
func inlineMethod1() {}
}
}

其实换个角度,inline function就是一个function,只是在Objective-C时代,function是不支持嵌套的,而Swift提供了这个支持,当然还支持多层嵌套,不过有一个需要注意的是因为是还是属于本地声明,还是需要先定义后使用,因此声明的位置相比class层级的function更需要注意。

一般的使用

那既然在Objective-C的时代我们都不需要用到,那Swift下有什么作用呢?例如我们经常编写的初始化视图代码:

loadView 下面参杂了大量不同的初始化代码,写的时候或许还比较清晰,但过段时间在看的话就会感觉很混乱。当然注释也是个很好的区分方法,但注释每个人编写的习惯不一样,而且跟内容没有直接相关性,所以经常会出现注释跟不上代码的情况,因此直接把注释的内容赋予到代码上面是更好的方法,其实也就是抽取成function,例如这样:

这应该是我们最常用的方式了,抽取出来的function让包裹的代码更容易理解,处理起来也更方便,但有个问题是这些暴露出来的 initxxx() 方法在内部任何地方都可以直接调用到,虽然我们知晓他们只是作为 loadView 一次性调用的初始化代码,但约定始终没有限制来得问题,这时候我们就可以用inline function来解决这个问题:

把三个 initxxx() 方法换成inline function,保留了代码的结构性,同时避免了可能发生的错误调用情况,同时为后期重构提供了帮助,因为相关代码更为紧凑并不会分散到各个地方。

减少重复代码

减少重复代码向来都是function的责任,但以前只有class层级function的时候,我们通常只会把通用的重复代码抽取成function,一些局部重复使用的代码,我们都是直接重复调用相同代码,而很少去抽取function,因为如果每个局部逻辑都抽取function的话,我们class层级的function就太多太杂乱了。

如下面这个示例,label.text 有多个重复的设置,示例可能还算简单,但我们始终需要维护两组字符串的一致性。

但有了inline function,我们就可以把DRY准则贯彻得更为彻底,让复杂的部分得到充分的重用,就像下面这个效果:

事实上,我们还可以利用function的其他特性,例如参数传递,就能让我们的代码更结构化:

回调优化

除了优化一些class层级原有的function,其实inline function还可以用来优化一些回调处理的问题。举个例子,我们经常需要做网络请求,会存在多个回调,例如下图示例:

但像这样请求参数多的时候,整个方法调用就会很长显示很不清晰,整理清晰一点,我们可以用换行来处理,但这时候你就要忍受Xcode的奇葩缩进逻辑:

参数已经很清晰,但回调内容缩进层级高,而且 } 的缩进位置我个人不太能接受。这时候我们就可以用inline function来处理这个问题,添加两个inline function后,我们可以调整成这个效果:

其实如果把 onSuccessonFailure 两个方法抽取到class层,就是我们大家都熟悉的方式,但使用inline function的好处是这两个方法不会影响到其他方法,就相当于限制了这些方法的作用域。而且整个代码的结构就会表达比较整洁,缩进层级也不高。

这些简单的示例可能还体现不到使用inline function的必要性,但想象一下如果有多个请求同时进行,然后需要做一些共同的处理,这时候如果把function都放到class层级的话,就会对其他class内部的方法造成很大干扰,但如果使用inline function的话,就能依然保持结构性和低干扰性,例如下面这个示例:

其实inline function就是能让我们的function分散在更适合的地方而不是全部集中于class和struct之类的层级,像是把我们本来class下的 private func 以更细的层级进行区分。

  • 如果你对文中的内容有疑问或者建议,欢迎留言讨论。
  • 如果你觉得文中内容有价值,请转发让更多人可以看到。
  • 如果你喜欢这类型内容,欢迎follow我的MediumTwitter,我会持续发布更多有用内容给大家。

--

--

Galvin Li

A Tiny iOS developer who love to solve problems and make things better.