Swift函数提前返回实例详解
简评:
函数是一个组织在一起语句集合,以执行特定任务。Swift 函数类似于简单 C 函数以及复杂的 Objective C 语言函数。 它使我们能够通过函数调用内部的局部和全局参数值。 像其他任何语言一样 swift 函数也遵循相同的步骤。
- 函数声明:它告诉编译器有关的函数的名称,返回类型和参数。
- 函数定义:它提供函数的实际主体。
Swift 函数包含参数类型和返回类型。
函数提前返回主要的好处是:将每个错误处理进行分离,审查代码时不需要考虑多种复杂异常,我们可以吧注意力集中在也业务逻辑中,调试代码时可以直接在异常中打断点。
提前返回
首先来看一下需要改进的代码示例,我们构建一个笔记应用使用 NotificationCenter API,当笔记内容有变化时 Notification 来通知笔记列表变更,代码如下:
class NoteListViewController: UIViewController { @objc func handleChangeNotification(_ notification: Notification) { let noteInfo = notification.userInfo?["note"] as? [String : Any] if let id = noteInfo?["id"] as? Int { if let note = database.loadNote(withID: id) { notes[id] = note tableView.reloadData() } } } }
上面的代码可以很好的工作,但是可读性差了点。因为这段代码包含多重缩进和类型转换。我们来尝试改进这段代码。
- 将方法提前返回,让我们函数尽可能的快的返回。
- 使用 guard 替代 if,以避免嵌套。
class NoteListViewController: UIViewController { @objc func handleChangeNotification(_ notification: Notification) { let noteInfo = notification.userInfo?["note"] as? [String : Any] guard let id = noteInfo?["id"] as? Int else { return } guard let note = database.loadNote(withID: id) else { return } notes[id] = note tableView.reloadData() } }
将函数提前返回能够将功能失败的情况处理得更加清晰,这不仅提高了可读性(更少的缩进,更少的嵌套),同时也有利于单元测试。
我们可以进一步改进代码,将获取 noteID 和类型转换的代码放在 Notification Extension 中,这样就将 handleChangeNotification 业务逻辑和具体细节分离开来。修改后代码如下所示:
private extension Notification { var noteID: Int? { let info = userInfo?["note"] as? [String : Any] return info?["id"] as? Int } } class NoteListViewController: UIViewController { @objc func handleChangeNotification(_ notification: Notification) { guard let id = notification.noteID else { return } guard let note = database.loadNote(withID: id) else { return } notes[id] = note tableView.reloadData() } }
这种结构还大大简化了调试的难度,我们可以直接在每个 guard 中 return 中添加断点来截获所有失败情况,而不需要单步执行所有逻辑。
条件构造
当构造一个对象实例,非常普遍的需求是需要构建哪类对象取决于一系列的条件。
例如,启动应用程序时显示哪个 view controller 取决于:
- 是否已经登录。
- 用户是否已经完成入职流程(onboarding flow)。
我们对这些条件的的实现可能是一系列的 if 和 else 语句,如下所示:
func showInitialViewController() { if loginManager.isUserLoggedIn { if tutorialManager.isOnboardingCompleted { navigationController.viewControllers = [HomeViewController()] } else { navigationController.viewControllers = [OnboardingViewController()] } } else { navigationController.viewControllers = [LoginViewController()] } }
同样的提前返回和 guard 语句可以提升代码可读性,但是现在这种情况不是处理失败情况,而是在不同条件下构建不同 view controller。
现在来改进这段代码,使用轻量级的工程模式,将构造初始界面移动到专门的函数中,该函数返回匹配条件的view controller。如下所示:
func makeInitialViewController() -> UIViewController { guard loginManager.isUserLoggedIn else { return LoginViewController() } guard tutorialManager.isOnboardingCompleted else { return OnboardingViewController() } return HomeViewController() } func showInitialViewController() { let viewController = makeInitialViewController() navigationController.viewControllers = [viewController] }
由于 makeInitialViewController 方法是个纯函数(不影响外部状态,固定输入能够得到固定输出),实际上影响外部状态的只有一个地方 navigationController.viewControllers = [viewController] ,(在日常开发中状态如果没有得到很好的控制很容易引起 bug,所以使用更少状态和减少对状态的修改可以一定程度上减少 bug 出现的几率)。
条件控制
最后我们来看看,函数如何简化复杂的条件逻辑。我们来构建一个 view controller 来显示社交应用的评论功能,如果满足三个条件则运行用户对评论进行编辑。代码如下:
class CommentViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() if comment.authorID == user.id { if comment.replies.isEmpty { if !comment.edited { let editButton = UIButton() ... view.addSubview(editButton) } } } ... } }
这里使用了 3 个 if 嵌套逻辑,每次重新审查代码都会比较困扰,更具之前的经验我们可以对代码进行优化,添加 Comment extension:
extension Comment { func canBeEdited(by user: User) -> Bool { guard authorID == user.id else { return false } guard comment.replies.isEmpty else { return false } return !edited } } class CommentViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() if comment.canBeEdited(by: user) { let editButton = UIButton() ... view.addSubview(editButton) } ... } }
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对猪先飞的支持。
相关文章
- eval函数在php中是一个函数并不是系统组件函数,我们在php.ini中的disable_functions是无法禁止它的,因这他不是一个php_function哦。 eval()针对php安全来说具有很...2016-11-25
- 在php中eval是一个函数并且不能直接禁用了,但eval函数又相当的危险了经常会出现一些问题了,今天我们就一起来看看eval函数对数组的操作 例子, <?php $data="array...2016-11-25
Python astype(np.float)函数使用方法解析
这篇文章主要介绍了Python astype(np.float)函数使用方法解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下...2020-06-08- 这篇文章主要介绍了Python中的imread()函数用法说明,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2021-03-16
- 本文主要介绍了C# 中取绝对值的函数。具有很好的参考价值。下面跟着小编一起来看下吧...2020-06-25
- 下面小编就为大家带来一篇C#学习笔记- 随机函数Random()的用法详解。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧...2020-06-25
- 这篇文章主要介绍了mybatis-plus 返回部分字段的解决方式,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-10-02
- CREATE FUNCTION ChangeBigSmall (@ChangeMoney money) RETURNS VarChar(100) AS BEGIN Declare @String1 char(20) Declare @String2 char...2016-11-25
Android开发中findViewById()函数用法与简化
findViewById方法在android开发中是获取页面控件的值了,有没有发现我们一个页面控件多了会反复研究写findViewById呢,下面我们一起来看它的简化方法。 Android中Fin...2016-09-20- 这篇文章主要介绍了C++中Sort函数详细解析,sort函数是algorithm库下的一个函数,sort函数是不稳定的,即大小相同的元素在排序后相对顺序可能发生改变...2022-08-18
- strstr() 函数搜索一个字符串在另一个字符串中的第一次出现。该函数返回字符串的其余部分(从匹配点)。如果未找到所搜索的字符串,则返回 false。语法:strstr(string,search)参数string,必需。规定被搜索的字符串。 参数sea...2013-10-04
PHP函数分享之curl方式取得数据、模拟登陆、POST数据
废话不多说直接上代码复制代码 代码如下:/********************** curl 系列 ***********************///直接通过curl方式取得数据(包含POST、HEADER等)/* * $url: 如果非数组,则为http;如是数组,则为https * $header:...2014-06-07- Foreach 函数(PHP4/PHP5)foreach 语法结构提供了遍历数组的简单方式。foreach 仅能够应用于数组和对象,如果尝试应用于其他数据类型的变量,或者未初始化的变量将发出错误信息。...2013-09-28
- free函数是释放之前某一次malloc函数申请的空间,而且只是释放空间,并不改变指针的值。下面我们就来详细探讨下...2020-04-25
SQLMAP结合Meterpreter实现注入渗透返回shell
sqlmap 是一个自动SQL 射入工具。它是可胜任执行一个广泛的数据库管理系统后端指印, 检索遥远的DBMS 数据库等,下面我们来看一个学习例子。 自己搭建一个PHP+MYSQ...2016-11-25- PHP 函数 strip_tags 提供了从字符串中去除 HTML 和 PHP 标记的功能,该函数尝试返回给定的字符串 str 去除空字符、HTML 和 PHP 标记后的结果。由于 strip_tags() 无法实际验证 HTML,不完整或者破损标签将导致更多的数...2014-05-31
SQL Server中row_number函数的常见用法示例详解
这篇文章主要给大家介绍了关于SQL Server中row_number函数的常见用法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2020-12-08- 分享一个PHP加密解密的函数,此函数实现了对部分变量值的加密的功能。 加密代码如下: /* *功能:对字符串进行加密处理 *参数一:需要加密的内容 *参数二:密钥 */ function passport_encrypt($str,$key){ //加密函数 srand(...2015-10-30
php的mail函数发送UTF-8编码中文邮件时标题乱码的解决办法
最近遇到一个问题,就是在使用php的mail函数发送utf-8编码的中文邮件时标题出现乱码现象,而邮件正文却是正确的。最初以为是页面编码的问题,发现页面编码utf-8没有问题啊,找了半天原因,最后找到了问题所在。 1.使用 PEAR 的...2015-10-21- 下面小编就为大家带来一篇C#中加载dll并调用其函数的实现方法。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧...2020-06-25