为何我从 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 优势。

相关文章
相关标签/搜索