Swift学习

Swift 5.1 中引入的部分有用的新特性

2020-01-19  本文已影响0人  韦弦Zhy

Swift 5.1现在已经正式发布,尽管只是次要版本,它包含了大量的更改和改进。从基本的新功能,例如模块稳定性(使SDK供应商可以交付预编译的Swift框架)到所有SwiftUI以及其他功能的新语法功能。

除了具有标题的新功能外,Swift 5.1还包含许多较小的但仍然非常重要的新功能和改进。乍一看,这种变化似乎很小,甚至是不必要的,但可能会对我们编写和构建Swift代码的方式产生重大影响。 Swift 5.1 - 简书

1、函数、闭包单表达式函数的隐式返回

//单行表达式
func increase(number: Int) -> Int {
    number + 1
}

//计算属性
struct Message {
    var title: String
    var info: String
    let description: {title + ": " + info}
}

2、具有默认值的成员初始化器----自动合成结构体的构造参数

struct Message {
    var title: String
    var info: "body"
}

在swift 5.1 中,下方初始化方法均正确

var message = Message(title: "title")
var message = Message(title: "title", info: "info body")

3、Self 关键字

3.1、静态成员的 Self
class ListViewController: UITableViewController {
    static let cellReuseIdentifier = "list-cell-identifier"

    override func viewDidLoad() {
        super.viewDidLoad()

        tableView.register(
            ListTableViewCell.self,
            forCellReuseIdentifier: Self.cellReuseIdentifier
        )
    }
}
3.2、使用 Self 动态获取引用类型
extension Numeric {
    func incremented(by value: Self = 1) -> Self {
        return self + value
    }
}
let num1 = 5.incremented()           //num1: Int
let num2 = 5.0.incremented()         //
3.3 使用Self引用封闭类型
struct TextTransform {
    let closure: (String) -> String
}

extension TextTransform {
    static var capitalize: Self {
        return TextTransform { $0.capitalized }
    }

    static var removeLetters: Self {
        return TextTransform { $0.filter { !$0.isLetter } }
    }
}

我们现在可以在上方使用Self而不是完整的TextTransform类型名称看,当然这纯粹是语法糖——但它可以使我们的代码更紧凑,尤其是在处理长类型名称时。我们甚至还可以在方法或属性中使用Self内联,同时使用隐式返回,进一步使上述代码更加紧凑:

extension TextTransform {
    static var capitalize: Self {
        Self { $0.capitalized }
    }

    static var removeLetters: Self {
        Self { $0.filter { !$0.isLetter } }
    }
}

给String扩展两个方法:

extension String {
    func withTransform(_ textTransform: TextTransform) -> String {
        textTransform.closure(self)
    }
    
    mutating func withTransforms(_ textTransforms: [TextTransform]) -> String {
        textTransforms.forEach{ trans in
            self = self.withTransform(trans)
        }
        return self
    }
}

let singelUse = "i am a string"
    .withTransform(.capitalize)
    .withTransform(.removeLetters)

var str = "i am a string"
let groupUse = str.withTransforms([
    .capitalize,
    .removeLetters
])

4、属性包装类型(Property Wrapper Types)

在 iOS 开发中,经常要用到@IBOutlet@IBAction,在Swift中,越来越多@修饰的关键字出现,比如 @UIApplicationMain,特别是在 SwiftUI 中,会发现有很多类似这样的关键字。

@propertyWrapper
struct Trimmed {
    private var value: String = ""
    var wrappedValue: String {
        get { value }
        set { value = newValue.trimmingCharacters(in: .whitespacesAndNewlines) }
    }
    init(wrappedValue initialValue: String) {
        self.wrappedValue = initialValue
    }
}

struct Message {
    @Trimmed var title: String
    @Trimmed var info: String
}
//任何字符串无论是在初始化期间还是通过后面的属性访问都会自动删除前后面的空格。
var msg = Message(title: "  Swift5.1 Property Wrappers  ", info: "  is a new and important  key words")
let title = msg.title // "Swift5.1 Property Wrappers"
let info = msg.info  // "is a new and important  key words"

5、有序集合的差异

class DatabaseController<Model: Hashable & Identifiable> {
    private let database: Database
    private(set) var models: [Model] = []
    
    ...

    func update(with newModels: [Model]) {
        let diff = newModels.difference(from: models)

        for change in diff {
            switch change {
            case .insert(_, let model, _):
                database.insert(model)
            case .remove(_, let model, _):
                database.delete(model)
            }
        }

        models = newModels
    }
}
func update(with newModels: [Model]) {
    let diff = newModels.difference(from: models).inferringMoves()
    
    for change in diff {
        switch change {
        case .insert(let index, let model, let association):
            // 如果 associated index 不为 nil, 则意味着这个inset操作实际上是move
            if association != nil {
                database.move(model, toIndex: index)
            } else {
                database.insert(model)
            }
        case .remove(_, let model, let association):
            // 我们将只处理 association 为 nil的情况,其他情况已经在上方处理
            if association == nil {
                database.delete(model)
            }
        }
    }

    models = newModels
}

6、将协议抛出错误功能实现为非抛出

protocol TokenParser {
    func parseToken(from string: String) throws -> Token
}
struct KeywordParser: TokenParser {
    func parseToken(from string: String) throws -> Token {
        ...
    }
}

struct TextParser: TokenParser {
    //这仍然能够符合我们的协议,虽然它没有 throws
    func parseToken(from string: String) -> Token {
        ...
    }
}
let parsers: [TokenParser] = ...

for parser in parsers {
    let token = try parser.parseToken(from: string)
}
let parser = TextParser()
let text = parser.parseToken(from: string)

7、字符串插值新协议ExpressibleByStringInterpolation——使类型可以使用字符串插值

struct Path {
    var string: String
}

func loadFile(at path: Path) throws -> File {
    ...
}
try loadFile(at: Path(string: "~/documents/article.md"))
extension Path: ExpressibleByStringLiteral {
    init(stringLiteral value: String) {
        self.string = value
    }
}
try loadFile(at: "~/documents/article.md")
try loadFile(at: "/users/\(username)/file.txt")

现在,swift5.1引入了新协议ExpressibleByStringInterpolation,只要使Path遵循这个协议,则上面的代码就可以正常运行了,增加如下代码:

extension Path: ExpressibleByStringInterpolation {}

8、返回值类型抽象化 —— some关键字

这里的some其实就是和一个称为opaque(不透明)类型有关,在返回类型前面加上一些关键字表示返回类型是不透明的,不透明类型通常被称为反向泛型类型。
比如我定一个一个Animal协议,具有关联类型LikeType

protocol Animal {
    associatedtype LikeType
    var name: String { get }
    var like: LikeType { get }
}

struct Dog: Animal {
    var name: String
    var like: Bark
}

struct Pig: Animal {
    var name: String
    var like: Sleep
}

此时我们实现一个方法去识别动物:

func identityAnimal() -> Animal

这在swift中是无法编译通过的,因为swift不能把带有关联类型的协议类型作为返回类型,这个时候就轮到some上场了:

func identityAnimal() -> some Animal {
    return Pig(name: "pink pig", like: Sleep("every day"))
}

var animal: some Animal = identityAnimal()

参考文档:
5 small but significant improvements in Swift 5.1
Implementing throwing protocol functions as non-throwing
Making types expressible by string interpolation

上一篇下一篇

猜你喜欢

热点阅读