Writing Better Swift Code: Tips and Tricks

add prefix

In order to avoid naming conflicts, in the OC era, our approach is to add snp_/sd_a similar , in Swiftwhich we have a more elegant way of handling:

struct OD<Base> {
    var base: Base
    init(_ base: Base) {
        self.base = base
    }
}

protocol ODCompatible {
    var od: OD<Self> {get}
    static var od: OD<Self>.Type {get}
}

extension ODCompatible {
    var od: OD<Self> {
        OD(self)
    }
    static var od: OD<Self>.Type {
        OD<Self>.self
    }
}

extension String: ODCompatible {}
extension OD where Base == String {
    // 添加方法
    func test() {
        print("\(self)::\(self.base)")
    }
}

"A".od.test() // OD<String>(base: "A")::A
复制代码

Quick exchange of values

For this, we can quickly write:

// 普通方法:
func swapMe1<T>( a: inout T, b: inout T) {
    let temp = a
    a=b
    b = temp 
}
复制代码

A temporary variable temp needs to be introduced, so can the values ​​of the two numbers be exchanged without going through the third bucket?

// 使用多元组:
func swapMe2<T>( a: inout T, b: inout T) {
    (a,b) = (b,a)
}
复制代码

@discardableResult discardable result

Swift is a very strict language. When the return value of a function is not used, the compiler will prompt related warnings. We can @discardableResulttell the compiler not to generate warnings by declaring the function as a discardable result:


func woo() -> String {
    return "oldbird.run"
}

@discardableResult
func bar() -> String {
    return "关注 Oldbirds 公众号"
}

woo() // WARNING: Result of call to 'woo()' is unused

// 当然也可以赋值到占位符 _ 以避免警告
_ = woo()

bar()
复制代码

Access control

Access control restricts the level of access to your code by code in other source files or modules. You can explicitly set access levels for individual types (classes, structs, enums), and also for properties, functions, initialization methods, primitive types, subscript indexes, etc. of these types.

Swift provides four different access levels for entities in code: open, public, internal, fileprivate, private.

-w417

  • openThe sum publiclevel allows entities to be accessed by all entities in the source file of the same module, and can also be accessed outside the module by importing the module to access all entities in the source file. Typically, you would use the openor publiclevel to specify the framework's external interface. openIt can only act on classes and class members. publicThe main difference between it and class is that openlimited classes and members can be inherited and overridden outside the module.
  • internalThe level makes the entity accessible to any entity in the same module source file, but not to entities outside the module. Typically, if an interface is only used internally by an application or framework, it can be set to a internallevel.
  • fileprivateRestricts entity access only inside the file in which it is defined. If part of the implementation detail of the function is only needed within the file, it can be used fileprivateto hide it.
  • private限制实体只能在其定义的作用域,以及同一文件内的extension访问。如果功能的部分细节只需要在当前作用域内使用时,可以使用private来将其隐藏。
  • 除非专门指定,否则实体默认的访问级别为internal

更多控制细节,可参考翻译文档

在 for 循环中使用 where

对于简单的循环,使用 where 非常富有表现力。

func archiveMarkedPosts() {
    for post in posts where post.isMarked {
        archive(post)
    }
}

func healAllies() {
    for player in players where player.isAllied(to: currentPlayer) {
        player.heal()
    }
}
复制代码

Guess you like

Origin juejin.im/post/7012541709561102367