Copy // `reduce(_:_:)`
func reduce < Result > (
_ initialResult : Result,
// ⭐️ combine function (with return value)
_ nextPartialResult : (Result, Element ) throws -> Result
) rethrows -> Result
// `reduce(into:_:)`
func reduce < Result > (
into initialResult : Result,
_ updateAccumulatingResult : (
_ partialResult: inout Result, // ⭐️ inout parameter
Self. Element
) throws -> () // ⭐️ no return value
) rethrows -> Result
我們用合併 SwiftUI 中的 transitions 來舉例,說明這兩者的用法有哪些不同。在合併 SwiftUI 中的 transitions 時,使用 SwiftUI 原有的語法,顯得太過冗長:
Copy AnyTransition
. move ( edge : .leading )
. combined ( with : .opacity )
. combined ( with : .scale )
Copy // 無法自行推斷 (infer) AnyTransition 型別的時候:
AnyTransition ( .move ( edge : .leading ) , .opacity, .scale )
// 可以自行推斷 AnyTransition 型別的時候:
. combined ( .move ( edge : .leading ) , .opacity, .scale )
Copy extension AnyTransition {
// ⭐️ combining transitions
// AnyTransition([.scale, .opacity, ...]) ........ (1)
init ( _ transitions : [AnyTransition]) {
// use reduce() or reduce(into:)
}
// 讓可以使用的語法更豐富,在可以使用 AnyTransition 的地方,直接用:
// .combined(.move, .scale, ...)
public static func combined ( _ transitions : AnyTransition ... ) -> AnyTransition {
. init ( transitions )
}
}
extension AnyTransition : ExpressibleByArrayLiteral {
// convenience init
// AnyTransition(.move, .scale, .opacity, ...)
public init ( arrayLiteral elements : AnyTransition ... ) {
self. init ( elements ) // 使用 (1)
}
}
Copy init ( _ transitions : [AnyTransition]) {
let intialValue = AnyTransition. identity
// ⭐️ 使用 `reduce(_:_)`
self = transitions. reduce ( intialValue ) { (result, transition) in
// ⭐️ 下面的結果會「自動成為新的 `result`」,不需手動改寫 `result`
// 所以官方稱這個部分的 closure 為:`nextPartialResult`。
result. combined ( with : transition ) // ⭐️ implicit return
}
}
Copy init ( _ transitions : [AnyTransition]) {
var intialValue = AnyTransition. identity
// ⭐️ 使用 `reduce(into:_:)`
self = transitions. reduce ( into : intialValue ) { (result, transition) in
// ⭐️ 記得手動改寫 `result` 變數,否則效果並不會累加。
// 因為如果我們不寫 `result = ...`,這時 `result` 變數
// 並不會自動改變,所以官方稱這個部分為 `updateAccumulatingResult`
// 而不是 `nextPartialResult`。
result = result. combined ( with : transition ) // ⭐️ no return value
}
}