Key-Value Coding Programming Guide - Key-Value Coding Fundamentals - Using Collection operators
KVC를 이용해서 valueForKeyPath:를 할 때 collection operator를 키패스에 넣어 사용할 수 있습니다.
아래 이미지와 같이 사용합니다. collectionOperator는 몇 가지 있고, 리턴값을 받기 전에 collection data를 operator에 맞게 조작해서 값을 리턴합니다 ( avg, sum, count, etc). 이런 기능은 NSObject 구현돼 있습니다.

- Left key path : 컬렉션 위치를 표시하는 키패스
* 콜랙션에 바로 접근할 경우에 left key path는 없어도 됩니다.
- Collection operator : 연산자
- Right key path : 프로퍼티까지의 키 패스
* @count 연산자 를 제외하고는 right key path 무조건 있어야 됩니다.
Collection operator는 기본적으로 세가지 유형이 있습니다.
1. Aggregation Operators
콜렉션에 있는 객체들을 종합해서 매치되는 하나의 객체를 반환합니다. right key path에 있는 프로퍼티의 데이터 값을 가지고 연산합니다.. @count 예외로 right key path가 없고 항상 NSNumber을 리턴합니다.
2. Array Operators
연산자에 의해 콜랙션 객체 subset이 만들어지고 그것을 리턴합니다.
3. Nesting Operators
중첩컬렉션(컬렉션 안에 있는 컬렉션)을 다룰 때 씁니다.. 연산자에 따라서 중첩된 컬렉션의 객체들을 연산해서 NSArray나 NSSet 인스턴스를 반환한다.
- Some Data
데이터는 아래 주소에서 다운 받으실 수 있습니다. 다운 받아서 아래 설명과 같이 보시면 좋습니다. 아래 설명에서는 한 두개만 보면 나머지를 알 수 있기 때문에 몇몇은 생략했습니다.
- Aggregation Operators
array나 set을 다룰 때 쓰고 연산 결과를 반환합니다.
@avg
right key path에 있는 array나 set 요소드를 하나씩 double로 변환(nil이면 0으로 대체)하고 평균값을 계산해서 NSNumber에 담아 반환합니다. 아래 코드는 평균값인 $456.62를 반환합니다.
NSNumber *transactionAverage = [self.transactions valueForKeyPath:@"@avg.amount"];
@count
컬랙션 객체에 있는 요소 개수를 NSNumber에 담아 반환합니다. @count는 예외적으로 right key path가 없습니다. 만약 있다면 무시합니다. 아래 코드는 13은 반환합니다.
NSNumber *numberOfTransactions = [self.transactions valueForKeyPath:@"@count"];
@max, @min, @sum 등등도 다 예상되로 작동합니다. 소스 보시면서 확인하면 좋습니다.
- Array Operators
right key path에 해당하는 프로퍼티들를 가지고 연산(교집합, 합집합)을 해서 array로 반환합니다.
단, valueForKeyPath메서드는 array operators를 할 때 프로퍼티가 nil인게 있으면 exception을 일으킵니다.
@distinctUnionOfObjects
right key path에 해당하는 값들을 모아서 중복 제거를 한 후 array에 담아서 반환합니다. 아래 코드는 Car Loan, General, Cable, Animal Hospital, Green Power, Mortgage를 반홥합니다.
NSArray *distinctPayees = [self.transactions valueForKeyPath:@"@distinctUnionOfObjects.payee"];
@unionOfObjects
@distinctUnionOfObjects의 반대입니다. 모든 payee들을 모아서 반환합니다.
NSArray *payees = [self.transactions valueForKeyPath:@"@unionOfObjects.payee"];
- Nesting Operators
중첩 array나 set을 연산합니다. 역시나 연산대상인 객체들 중 nil이 있으면 예외를 발생합니다.
아래 moreTransactions은 table 4-2에 데이터들로 채워집니다. 소스코드에서도 볼 수 있습니다.
NSArray* moreTransactions = @[<# transaction data #>];
NSArray* arrayOfArrays = @[self.transactions, moreTransactions];
Table 4-2Hypothetical Transaction
data in the moreTransactions
arraypayee values
| amount values formatted as currency
| date values formatted as month day, year
|
---|
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 Shop
| $600.00
| Jun 14, 2016
|
https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/KeyValueCoding/CollectionOperators.html#//apple_ref/doc/uid/20002176-BAJEAIEE
@ distinctUnionOfArrays
중첩 array에 대해서 중복제거 연산을 한 후 array로 결과를 리턴합니다.
NSArray *collectedDistinctPayees = [arrayOfArrays valueForKeyPath:@"@distinctUnionOfArrays.payee"];
@ unionOfArrays
@ distinctUnionOfArrays의 반대입니다.
@ unionOfSets
@ distinctUnionOfArrays와 같습니다. 다른점은 중첩 NSSet대상으로 한다는 점입니다. 또한 NSSet을 리턴합니다. 합집합이지만 결과는 @ distinctUnionOfArrays와 같습니다. 왜냐하면 set은 기본적으로 중복을 제거하기 때문입니다.
arrayOfarraysOfarrays로 해봤는데 돌아가긴 하는데 값이 엉망입니다.
* 추가적으로 2
가이드에서는 left key path를 사용하는 모습을 볼 수 없어서 예제를 추가 했습니다. 보통 to-many 관계에서 사용합니다. 아래와 같이 사용합니다. 소스코드에서도 확인할 수 있습니다.
// example using left key path
BankAccount *bankAccount = [BankAccount new];
bankAccount.transactions = @[aTransaction, bTransaction];
NSLog(@"%@", [bankAccount valueForKeyPath:@"transactions.@count"]); // 2
NSLog(@"%@", [bankAccount valueForKeyPath:@"transactions.@avg.amount"]); // 135
NSLog(@"%@", [bankAccount valueForKeyPath:@"transactions.@distinctUnionOfObjects.payee"]); // Grren Power
* 추가적으로 3
대게 이런 작업은 for문으로 하는데 key path를 하면 편하게 할 수 있습니다. 쉽게 계층 구조를 파고들어 컬랙션에 연산을 적용하고 값을 받을 수 있습니다. 하지만 기본적으로 KVC 간접적으로 접근합니다. 문서에도 있는데 검색 패턴이 있습니다. 문자열을 파싱해서 하는데 딱봐도 느릴 거 같다는 생각이 듭니다. 그리고 key path에 오타를 내도 컴파일러가 체크 해주지 않습니다. 실제로 실행해야 런타임에서 에러가 나는 걸 볼 수 있습니다.