Key-Value Coding Programming Guide 官方文件第二部分第3節 2018.9.20 第一次修正
Key-Value Coding Fundamatals--Using Collection Operators
使用集合運算子
當你向符合鍵值編碼的物件傳送valueForKeyPath:
訊息時, 可以在鍵路徑中嵌入集合運算子。集合運算子是一個小的關鍵字列表,前面帶一個at符號(@), 它指定了getter
應該執行的操作,以便在返回之前以某種方式運算元據。valueForKeyPath:
由NSObject
預設實現。
當鍵路徑包含集合運算子時, 運算子前面的鍵路徑的任何部分 (稱為左鍵路徑) 指向相對於訊息接收者操作的集合。如果將訊息直接傳送到集合物件 (例如NSArray
例項), 則可以省略左鍵路徑。操作符之後的鍵路徑部分(稱為右鍵路徑)指定操作符應處理的集合中的屬性。除了@count需要正確的鍵路徑之外,所有集合運算子。圖4-1說明了操作符鍵路徑格式。
圖 4-1運算子鍵路徑格式
集合運算子展示了三種基本行為型別:
-
聚合運算子以某種方式合併集合的物件,並返回通常與右鍵路徑中指定的屬性的資料型別匹配的單個物件。該
@count
運算子是一個例外,它沒有右鍵路徑並始終將返回一個NSNumber
例項。 -
陣列運算子返回一個
NSArray
例項,該例項包含命名集合中儲存的物件的某個子集。 -
巢狀操作符處理包含其他集合的集合,並根據操作符返回一個
NSArray
或NSSet
例項,它以某種方式組合巢狀集合的物件。
示例資料
下面描述包括演示如何呼叫每個運算子的程式碼段,以及執行此操作的結果。這依賴於BankAccount
類 (在[列表 2-1]中顯示), 它是一個儲存Transaction
物件的陣列。其中每一個都代表一個簡單的checkbook
條目, 如清單 4-1中所宣告的那樣。
清單 4-1Transaction物件的介面宣告
@interface Transaction : NSObject
@property (nonatomic) NSString* payee; // To whom
@property (nonatomic) NSNumber* amount; // How much
@property (nonatomic) NSDate* date; // When
@end
複製程式碼
為了便於討論, 假定BankAccount例項具有一個使用表4-1中顯示的資料填充的交易陣列, 並且您可以從BankAccount物件內部進行呼叫。
表 4-1Transactions物件的示例資料
payee | amount | date |
---|---|---|
Green Power | $120.00 | Dec 1, 2015 |
Green Power | $150.00 | Jan 1, 2016 |
Green Power | $170.00 | Feb 1, 2016 |
Car Loan | $250.00 | Jan 15, 2016 |
Car Loan | $250.00 | Feb 15, 2016 |
Car Loan | $250.00 | Mar 15, 2016 |
General Cable | $120.00 | Dec 1, 2015 |
General Cable | $155.00 | Jan 1, 2016 |
General Cable | $120.00 | Feb 1, 2016 |
Mortgage | $1,250.00 | Jan 15, 2016 |
Mortgage | $1,250.00 | Feb 15, 2016 |
Mortgage | $1,250.00 | Mar 15, 2016 |
Animal Hospital | $600.00 | Jul 15, 2016 |
聚合運算子
聚合運算子處理array
或set
屬性, 從而生成反映集合某些方面的單個值。
@avg
當指定@avg運算子時, valueForKeyPath:
讀取集合中每個元素的右鍵路徑指定的屬性, 將其轉換為double (nil值用0替代), 並計算這些值的算術平均值。
然後它返回儲存在NSNumber例項中的結果。
獲取表 4-1中示例資料之間的平均交易記錄金額:
NSNumber *transactionAverage = [self.transactions valueForKeyPath:@"@avg.amount"];
複製程式碼
transactionAverage
的格式化的結果為 $ 456.54。
@count
指定@count
運算子時, valueForKeyPath:返回一個包含集合中的物件個數的NSNumber例項。右鍵路徑 (如果存在) 將被忽略。
在transactions中獲取Transaction物件的數目:
NSNumber *numberOfTransactions = [self.transactions valueForKeyPath:@"@count"];
複製程式碼
numberOfTransactions
的值為13。
@max
指定@max
運算子時, valueForKeyPath:
在由右鍵路徑命名的集合項之間進行搜尋, 並返回最大值。搜尋使用compare:
方法進行比較, 該方法由許多Foundation類(例如NSNumber類)定義。因此, 由右鍵路徑指示的屬性必須包含一個對此訊息有意義響應的物件。搜尋忽略值為nil
的集合項。
在表 4-1中列出的交易記錄中, 獲取日期值 (即最新交易記錄的日期) 的最大數量:
NSDate *latestDate = [self.transactions valueForKeyPath:@"@max.date"];
複製程式碼
latestDate
的值為 Jul 15, 2016.
@min
指定@min
運算子時, valueForKeyPath:
在由右鍵路徑命名的集合項之間進行搜尋, 並返回最小值。搜尋使用compare:
方法進行比較, 許多基礎類 (如NSNumber
類) 中都有定義。因此, 由右鍵路徑指示的屬性必須持有對此訊息有意義響應的物件。搜尋忽略值為nil
的集合項。
在表 4-1中列出的事務中, 獲取日期值 (即最早的事務的日期) 的最短時間。
NSDate *earliestDate = [self.transactions valueForKeyPath:@"@min.date"];
複製程式碼
earliestDate
的值為 Dec 1, 2015.
@sum
指定@sum運算子時, valueForKeyPath:
讀取集合中每個元素的右鍵路徑指定的屬性, 將其轉換為double
(nil
值替換為 0), 並計算總和。然後返回儲存在NSNumber例項中的結果。
獲取表 4-1中示例資料之間的交易記錄金額的總和:
NSNumber *amountSum = [self.transactions valueForKeyPath:@"@sum.amount"];
複製程式碼
amountSum
的結果為 $ 5935.00。
陣列運算子
陣列運算子使valueForKeyPath:
返回與右鍵路徑指示的特定物件集相對應的物件陣列。
重要 在使用陣列運算子時, 如果有任何葉(
leaf
)物件為nil, 則valueForKeyPath:
方法將引發異常。
@distinctUnionOfObjects
指定@distinctUnionOfObjects
運算子時, valueForKeyPath:
將建立並返回一個陣列, 該陣列包含與右鍵路徑指定的屬性對應的集合的不同物件。
獲取transactions中的交易記錄的payee屬性值的集合, 並省略重複值:
NSArray *distinctPayees = [self.transactions valueForKeyPath:@"@distinctUnionOfObjects.payee"];
複製程式碼
生成的distinctPayees
陣列包含以下每一個字串例項:Car Loan, General Cable, Animal Hospital, Green Power, Mortgage
。
注意
@unionOfObjects
運算子提供類似的行為, 但不刪除重複的物件。
@unionOfObjects
指定@unionOfObjects
運算子時, valueForKeyPath:
將建立並返回一個陣列, 該陣列包含與由右鍵路徑指定的屬性對應的集合的所有物件。與@distinctUnionOfObjects
不同, 不會刪除重複物件。
獲取transactions
中的交易記錄的payee屬性值的集合:
NSArray *payees = [self.transactions valueForKeyPath:@"@unionOfObjects.payee"];
複製程式碼
生成的payees
陣列包含以下字串:Green Power, Green Power, Green Power, Car Loan, Car Loan, Car Loan, General Cable, General Cable, General Cable, Mortgage, Mortgage, Mortgage, Animal Hospital
.記錄了重複值。
注意
@distinctUnionOfArrays
運算子類似, 但刪除重複的物件。
巢狀運算子
巢狀運算子對巢狀集合進行操作, 集合本身的每個條目都包含一個集合。
重要 如果在使用巢狀運算子時, 有任何葉(
leaf
)物件為nil, 則valueForKeyPath:
方法將引發異常。
對於下面的說明, 請看第二個稱為moreTransactions
的資料陣列, 其中填充了表 4-2中的資料, 並與原來的transactions
陣列一起插入巢狀陣列:
NSArray* moreTransactions = @[<# transaction data #>];
NSArray* arrayOfArrays = @[self.transactions, moreTransactions];
複製程式碼
表 4-2 moreTransactions
陣列中假設的Transaction
資料
payee | amount | date |
---|---|---|
General Cable - Cottage | $120.00 | Dec 18, 2015 |
General Cable - Cottage | $155.00 | Jan 9, 2016 |
General Cable - Cottage | $120.00 | Dec 1, 2016 |
Second Mortgage | $1,250.00 | Nov 15, 2016 |
Second Mortgage | $1,250.00 | Sep 20, 2016 |
Second Mortgage | $1,250.00 | Feb 12, 2016 |
Hobby Sho | $600.00 | Jun 14, 2016 |
@distinctUnionOfArrays
指定@distinctUnionOfArrays
運算子時, valueForKeyPath:
建立並返回一個陣列, 其中包含與右鍵路徑指定的屬性相對應的所有集合的組合的不同物件。
在arrayOfArrays
中的所有陣列中獲取payee
屬性的不同值:
NSArray *collectedDistinctPayees = [arrayOfArrays valueForKeyPath:@"@distinctUnionOfArrays.payee"];
複製程式碼
生成的collectedDistinctPayees
陣列包含以下值: Hobby Shop, Mortgage, Animal Hospital, Second Mortgage, Car Loan, General Cable - Cottage, General Cable, Green Power
。
注意 @unionOfArrays運算子類似, 但不移除重複物件。
@unionOfArrays
指定@unionOfArrays
運算子時, valueForKeyPath:
建立並返回一個陣列, 其中包含與由右鍵路徑指定的屬性相對應的所有集合的組合的所有物件, 而不刪除重複項。
在arrayOfArrays
中的所有陣列中獲取payee
屬性的值:
NSArray *collectedPayees = [arrayOfArrays valueForKeyPath:@"@unionOfArrays.payee"];
複製程式碼
生成的collectedPayees
陣列包含以下值:Green Power, Green Power, Green Power, Car Loan, Car Loan, Car Loan, General Cable, General Cable, General Cable, Mortgage, Mortgage, Mortgage, Animal Hospital, General Cable
。
注意
@distinctUnionOfArrays
運算子類似, 但移除重複物件。
@distinctUnionOfSets
當指定@distinctUnionOfSets
運算子時, valueForKeyPath:
建立並返回一個NSSet
物件, 其中包含與由右鍵路徑所指定的屬性相對應的所有集合組合的不同物件。
此運算子的行為與@distinctUnionOfArrays
類似, 只是它需要一個包含NSSet
例項的NSSet
例項物件, 其中, 而不是包含NSArray
例項的NSArray
例項物件。此外, 它還返回一個NSSet
例項。假設示例資料已儲存在集合而不是陣列中, 則示例呼叫和結果與@distinctUnionOfArrays
中顯示的相同。
由於筆者水平有限,文中如果有錯誤的地方,或者有更好的方法,還望大神指出。 附上本文的所有 demo 下載連結,【GitHub】。 如果你看完後覺得對你有所幫助,還望在 GitHub 上點個 star。贈人玫瑰,手有餘香。