Swift Attributes

In this doc we will talk about some attributes in Swift that can help you write better code.

@autoclosure

@autoclosure is an attribute that automatically wraps an expression in a closure. It is useful when you want to delay the evaluation of an expression.

Code without @autoclosure:

1
2
3
4
5
6
7
func logIfTrue(_ predicate: () -> Bool) {
if predicate() {
print("True")
}
}

logIfTrue({ 2 > 1 })

Code with @autoclosure:

1
2
3
4
5
6
7
func logIfTrue(_ predicate: @autoclosure () -> Bool) {
if predicate() {
print("True")
}
}

logIfTrue(2 > 1)

As you can see, the code with @autoclosure is cleaner and more readable. Moreover, it is more efficient because the expression is not evaluated until it is needed.

@autoclosure 可以将一个表达式自动封装为一个闭包,从而在需要的时候才对表达式进行计算。这样可以提高代码的可读性和性能。

@discardableResult

@discardableResult is an attribute that tells the compiler that the return value of a function can be ignored. It is useful when you want to suppress the warning that occurs when the return value of a function is not used.

1
2
3
4
5
6
@discardableResult
func add(_ a: Int, _ b: Int) -> Int {
return a + b
}

add(1, 2)

In the code above, the return value of the add function is ignored, but no warning is generated because of the @discardableResult attribute.

@discardableResult 可以告诉编译器函数的返回值可以被忽略,从而避免因为忽略返回值而产生的警告。

@escaping

@escaping is an attribute that indicates that a closure parameter of a function can escape the function’s scope. It is useful when you want to store the closure for later execution.
The “scope” of a closure is the body of the function in which it is defined.

1
2
3
4
5
func doSomethingAsync(completion: @escaping () -> Void) {
DispatchQueue.main.async {
completion()
}
}

In the code above, the completion closure is stored and executed later, so it needs to be marked as @escaping.
Without the @escaping attribute, the compiler would generate an error because the closure would be deallocated when the function returns.

This is usually helpful when the compleiton closure needs to be executed after the function returns and in this way, the closure can be stored and executed later. Where is it stored? It is stored in the heap memory. Is the function stored in the heap memory? No, the function is stored in the stack memory.

If the method is a synchronous method, the closure will be executed immediately, and there is no need to store it in the heap memory.

1
2
3
func doSomethingSync(completion: () -> Void) {
completion()
}

@escaping 可以告诉编译器一个函数的闭包参数可以在函数的作用域之外执行。这对于需要存储闭包以便以后执行的情况非常有用。