Swift 3 Custom Operator
Swift 3 出來之後,之前參考別人寫 autolayout + custom operator
部分也跟著不能運作。
當然光靠內建 convert 是行不通的,最好的方式還是去看改版到底改了什麼。
於是就翻了 Xcode Release Notes …
The syntax for adding new operators has changed significantly. The new language model uses a more semantic model based on named precedence groups rather than magic numbers. This only affects declaring new operators such as >>> and not adding new overloads of existing operators such as ==. (SE-0077)
custom operator 語法有顯著的改變。
新語言模組是使用更有語義的模組,並基於 precedence groups
而非 magic numbers
這只會影響到 custom operator,而不會影響既有的 operator(overloads)
詳細請看 proposal : SE-0077
首先先回顧一下 Swift 2 之前 custom operator 定義跟使用方式,以及剛剛提到的 magic numbers
定義部分:
- 決定:前(
prefix
) 中(infix
) 後置(postfix
)
範例:infix
- 符號
範例:<~
- 結合律:左至右 右至左
範例:left
- 優先度:越大越先做
範例:125
Swift 2 1
2
3
4
5
6
7
8
9
10
11
12// 定義 custom operator
// 中置, 結合律:左至右,優先度 125
infix operator <~ {
associativity left
precedence 125 // magic numbers 150
}
// 定義 custom operator 功能
public func <~ (left: NSLayoutConstraint, right: UILayoutPriority) -> NSLayoutConstraint {
left.priority = right
return left
}
回過來看 Swift 3 該怎麼改,首先先回顧原本的 magic numbers
125
對照優先度: 120 < 125 < 130
再對照符號: &&
< <~
< ==
再對照 Swift 2: Conjunctive < target < Comparative
最後是 Swift 3: LogicalConjunctionPrecedence < target < ComparisonPrecedence
於是我們知道目標是處於 LogicalConjunctionPrecedence < target < ComparisonPrecedence
之間
這時才來看他所謂的更有語義的模組 precedence groups
首先需要先定義 custom precedencegroup 並給上名稱 precedencegroup YumeComparisonAssignmentPrecedence
因為目標是 infix
,所以一樣要定義結合律 associativity: left
接著是有語義的比大小
lowerThan: ComparisonPrecedence
higherThan: LogicalConjunctionPrecedence
1 | precedencegroup YumeComparisonAssignmentPrecedence { |
然後定義你的 custom operator
要使用哪一種 Precedence
1 | infix operator <~ : YumeComparisonAssignmentPrecedence |
最後是實現功能
1 | extension NSLayoutConstraint { |
小抱怨:預設 Precedence
必須到 Standard library changes 查找,有點麻煩。
1 | precedencegroup BitwiseShiftPrecedence { |