: Objective C가 아니라 코코아가 제공하는 인다이렉션
: 클래스의 함수나 변수 심지어 프로퍼티를 "키"값으로 불러서 사용 혹은 설정할 수 있다.
JAVA 리플렉션을 이용하여 클래스의 인스턴스를 얻지 않고 메소드나 변수에 접근할 수 있는데 거의 유사한 듯 한데…?
a. 기본
값을 얻을 때 -valueForKey:
값을 셋팅할 때 -setValue:forkey:
NSLog(@"horsepower is %@", [engine valueForKey:@"horsepower"]);
[engine setValue:[NSNumber numberWithInt:150] forKey:@"horsepower"];
b. 경로
!!! 와우!!!! 심지어 클래스를 따라 따라서도 접근이 가능하다…
값을 얻을 때 -valueForKeyPath:
값을 셋팅할 때 -setValue:forkeyPath:
[car setValue: [NSNumber numberWithInt: 155] forKeyPath: @"engine.horsepower"];
NSLog(@"horsepower is %@", [car valueForKeyPath: @"engine.horsepower"]);
c. Array의 값을 찾아서 다시 Array로 전달
NSArray *pressures = [car valueForKeyPath: @"tires.pressure"];
NSLog (@"pressures %@", pressures);
d. 연산자 사용
: 키경로에 객체 값 외에 몇몇 연산자를 사용하여 배열의 값의 평균, 합계, 갯수, 최대/최소값을 구할 수 있다
NSNumber *count = [garage valueForKeyPath:@"cars.@count"];
NSLog(@"We have %@ cars", count);
e. 키값을 한방에 수정
한방에 가져오기 : 원하는 키만 모아서 가져오기
NSArray *keys = [NSArray arrayWithObjects:@"make", @"model", @"modelYear", nil];
NSDictionary *carValues = [car dictionaryWithValuesForKeys:keys];
NSLog(@"Car values : %@", carValues);
한방에 수정: 일부 키를 한방에 수정
NSDictionary *newValues = [NSDictionary dictionaryWithObjectsAndKeys:
@"Chevy", @"make",
@"Nova", @"model",
[NSNumber numberWithInt:1964], @"modelYear",
[NSNumber numberWithFloat:987.6], @"mileage",
nil];
[car setValuesForKeysWithDictionary:newValues];
f. 비정의 값 처리 : 오버라이드 함수 구현해주면 됨
비정의 키에 대해서 설정할 때 처리함수
- (void) setValue:(id)value forUndefinedKey:
비정의 키에 대해서 값을 참고하려 할 때 처리함수
- (id) valueForUndefinedKey:
[참고] iOS 프로그래밍에서…
클래스간의 의존성을 낮출수록 좀 더 좋은 코드라고 한다. 키밸류코딩은 이러한 클래스간 의존성을 낮추는, 즉 느슨한 결합이 된 코드를 사용할 수 있다는 장점이 있다.
이경우 키밸류코딩의 단점은 상대클래스를 직접 호출하는 것이 아니므로 코드 가독성이 떨어질 수 있다. 또, 오타로 인해 버그로 이어질수도 있는 만큼 키-값 코딩을 남용해서는 안된다.
ex) 뷰콘트롤러의 Segue기능에서, 선택하면 Segue할 목적콘트롤러에게 값을 주기위해서 함수를 호출하는 방식에서 키밸류코딩을 사용한 경우
<키밸류코딩사용>
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
UIViewController *destination = segue.destinationViewController;
if ([destination respondsToSelector:@selector(setDelegate:)]) { //@property에 delegate에 대한 세터 혹은 setDelegate함수
[destination setValue:self forKey:@"delegate"]; //키밸류코딩(KVC) 활용
}
}
이 코딩을 직접메소드호출한다면… 임포트도 해야하고, 캐스팅도 해야한다. 즉 받는 애가 어떤 클래서인지 정확히 알고 갸의 메소드를 불러줘야 한다.
#import "BIDTaskDetailController.h"
...
//받는클래스가 어떤애인지 정확히 알고 캐스팅해야한다.
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
BIDTaskDetailController *destination = (BIDTaskDetailController *)segue.destinationViewController;
if (destination != nil) {
destination.delegate = self;
}
}