爲何我從 Objective-C 轉向 Swift

Swift 已經出了5個年頭了,到如今,它的語法已經很穩定,iOS developers 能夠放心使用了。我從1.0版本就開始使用 Swift,儘管也穿插了一些 Objective-C 項目,但整體來講還算用得熟手。目前團隊已經全面普及了 Swift,基本不會去寫 Objective-C 了。本文寫給還在用 Objective-C 的同行,但願大家認真考慮一下 Swift。程序員

理由1:實用的 Optional 特性

一開始接觸 Swift 的人可能會對 ?! 的操做很疑惑,甚至是渾身不自在。使用一段時間以後,就真香了。這個特性的用處是讓編譯器在編譯時就把nil異常檢測出來,讓開發者提早處理,從而不會把有這種問題的代碼發到線上去。swift

Swift 的編譯檢測很是強大,這也是一門純編譯語言的優點。我也兼職寫過一些 ruby 的後臺,對 ruby 的運行時空異常深惡痛絕。ruby

NoMethodError (undefined method `hello' for nil:NilClass)
複製代碼

你永遠都不想在線上出問題,這就是 Optional 特性的意義。bash

打個比方,我簡單地想使用一個url,這個url string是傳過來的。閉包

let someURLString = "https://Çhello world"
guard let url = URL(string: someURLString) else {
    fatalError("url went wrong \(someURLString)")
}

//..do something with url
print(url)
複製代碼

當個人url字符串含有非法字符的時候,我會獲得一個nil,並可能在後續下面的代碼拋出錯誤,致使crash。app

若是幸運的話,直接在當前的代碼塊就拋錯了,那還好修復。若是這個nil通過了不少層,那就糟糕了。網站

理由2:更加先進的枚舉

做爲一門全新的語言,Swift 站在巨人的肩膀上,把枚舉這種語言特性設計得簡直完美。 好比,你的枚舉類型能夠是字符串的。ui

enum Gender: String {
    case male
    case female
}
print(Gender.male.rawValue)
複製代碼

這樣的話,避免一堆未定義的字符串橫行。url

它還能夠在內部定義方法,或者返回一個值,還能夠遍歷。舉一個例子:spa

class ViewController: UIViewController {
    let tableView = UITableView()
    init() {
        CellType.allCases.forEach { (cellType) in
            cellType.register(to: tableView)
        }
    }
    
    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}
extension ViewController {
    enum CellType: String, CaseIterable {
        case business1
        case business2
        
        var cellId: String {
            return self.rawValue
        }
        
        func register(to tableView: UITableView) {
            switch self {
            case .business1: tableView.register(UITableViewCell.self, forCellReuseIdentifier: cellId)
            case .business2: tableView.register(UINib(nibName: "SomeCell", bundle: nil), forCellReuseIdentifier: cellId)
            }
        }
    }
}

複製代碼

當理解了業務是一種互斥關係的時候,用枚舉把這些列舉出來,並在內部處理以後,返回一個值,減小大量的if else,這樣組織的話,代碼就舒服了。

理由3:改進的閉包

Objective-C 的 block 在實用方面已經作得很好,Swift 的閉包在此基礎上再進一步。能夠直接在裏面聲明所捕獲的變量(好比self),衆周所知,閉包/block這種代碼組織方式可讓代碼更加緊湊,同時有捕獲局部變量的好處。可是當一個方法寫了一大塊,裏面含有一個閉包/block,不知道捕獲了什麼致使引用循環,這是難以調試的錯誤,所以在閉包內聲明所捕獲的變量是大有裨益的。

一般來講,這個用在 weak self 來弱引用 self 就能完成大部分的事情。

login(phone: "xxx", password: "pswd") { [weak self] (success) in
    self?.tableView.reloadData()
}
複製代碼

因爲 Swift 有空的檢測,因此只用 weak self 不會有問題,好比你在閉包執行這樣的代碼是不行的,直接報編譯錯誤:

var titles = [String]()
titles.append(self?.title)
複製代碼

可是 Objective-C 的block可能會有存在的問題

[titles addObject: weakSelf.title];
複製代碼

還有一點,或許是最重要的,就是咱們終於擺脫了 Objective-C 奇怪的 block 語法了!!這裏有一篇總結得很好(注意網站名) fuckingblocksyntax.com

理由4:養眼的代碼風格

最近看了一部紀錄片,叫《單挑荒野》,長期混B站的人可能熟悉,裏面的主人翁艾德一個主旨就是,不但要生存下去,並且要活得滋潤。程序員也同樣,不但要實現功能,還得優雅地實現,寫出讓本身感到滿意,舒服的代碼。

實現一樣的邏輯,Swift 可能不會比 Objective-C 少多少代碼,但必定好看,舒服。

好比,你不須要聲明這個變量的類型,由於在初始化的時候就已經知道。

let tableView = UITableView()
複製代碼

vs

UITableView *tableView = [[UITableView alloc] init];
複製代碼

好比枚舉,你會常常看到 Objective-C 這樣的代碼:

typedef NS_ENUM(NSInteger, UIModalTransitionStyle) {
    UIModalTransitionStyleCoverVertical = 0,
    UIModalTransitionStyleFlipHorizontal __TVOS_PROHIBITED,
    UIModalTransitionStyleCrossDissolve,
    UIModalTransitionStylePartialCurl NS_ENUM_AVAILABLE_IOS(3_2) __TVOS_PROHIBITED,
}
複製代碼

而 Swift 就舒服多了

enum UIModalTransitionStyle : Int {
    case coverVertical
    case flipHorizontal
    case crossDissolve
    case partialCurl
}
複製代碼

我不太喜歡用NSAttributedString,由於感受老是把代碼寫得亂糟糟,但在 Swift 則舒服得多。

let attributedString = NSAttributedString(
    string: "Hello world",
    attributes: [
    .font: UIFont.systemFont(ofSize: 14),
    .foregroundColor: UIColor.blue
    ]
)
複製代碼

還能夠稍微擴展一下 Int 類型,能夠寫出更簡潔明瞭的語句

extension Int {
    var font: UIFont {
        return UIFont.systemFont(ofSize: CGFloat(self))
    }
    var lineHeight: NSMutableParagraphStyle {
        let para = NSMutableParagraphStyle()
        para.maximumLineHeight = CGFloat(self)
        para.minimumLineHeight = CGFloat(self)
        return para
    }
}

let attributedString = NSAttributedString(
    string: "Hello world",
    attributes: [
    .font: 14.font,
    .paragraphStyle: 20.lineHeight,
    .foregroundColor: UIColor.blue
    ]
)
複製代碼

差很少就想到這些,權當盤磚引玉,短短篇幅也沒辦法覆蓋全部的 Swift 優勢。

相關文章
相關標籤/搜索