Swift函數提前返回實例詳解

函數相當重要的,下面這篇文章主要給大家介紹了關於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)
}

...
}
}

總結

以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,如果有疑問大家可以留言交流,謝謝大家對神馬文庫的支持。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章