[譯]2.3-Key-Value Coding Programming Guide 官方文件第二部分第3節

taoZen發表於2018-11-18

Key-Value Coding Programming Guide 官方文件第二部分第3節 2018.9.20 第一次修正

iOS-KVC官方文件第二部分第3節

Key-Value Coding Fundamatals--Using Collection Operators

使用集合運算子

當你向符合鍵值編碼的物件傳送valueForKeyPath:訊息時, 可以在鍵路徑中嵌入集合運算子。集合運算子是一個小的關鍵字列表,前面帶一個at符號(@), 它指定了getter應該執行的操作,以便在返回之前以某種方式運算元據。valueForKeyPath:NSObject預設實現。

當鍵路徑包含集合運算子時, 運算子前面的鍵路徑的任何部分 (稱為左鍵路徑) 指向相對於訊息接收者操作的集合。如果將訊息直接傳送到集合物件 (例如NSArray例項), 則可以省略左鍵路徑。操作符之後的鍵路徑部分(稱為右鍵路徑)指定操作符應處理的集合中的屬性。除了@count需要正確的鍵路徑之外,所有集合運算子。圖4-1說明了操作符鍵路徑格式。

圖 4-1運算子鍵路徑格式

4-1 Operator key path format.jpg

集合運算子展示了三種基本行為型別:

  • 聚合運算子以某種方式合併集合的物件,並返回通常與右鍵路徑中指定的屬性的資料型別匹配的單個物件。該@count運算子是一個例外,它沒有右鍵路徑並始終將返回一個NSNumber例項。

  • 陣列運算子返回一個NSArray例項,該例項包含命名集合中儲存的物件的某個子集。

  • 巢狀操作符處理包含其他集合的集合,並根據操作符返回一個NSArrayNSSet例項,它以某種方式組合巢狀集合的物件。

示例資料

下面描述包括演示如何呼叫每個運算子的程式碼段,以及執行此操作的結果。這依賴於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

聚合運算子

聚合運算子處理arrayset屬性, 從而生成反映集合某些方面的單個值。

@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。贈人玫瑰,手有餘香。

相關文章