函數相當重要的,下面這篇文章主要給大家介紹了關於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) } ... } }
總結
以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,如果有疑問大家可以留言交流,謝謝大家對神馬文庫的支持。