objective-c 프로그램은 런타임 시스템과 상호작용하기 위한 3가지 레벨이 있다.
1. Objectitve-C Source Code
- message call
2. NSObject Methods
- class, isKindOfClass, isMemberOfClass, respondsToSelector, conformsToProtocol, methodForSelector 등등
3. Runtime Functions
- 런타임 시스템은 dynamic shared library이다. 헤더파일들/usr/include/objc 디렉토리 안에 위치해 있다.
Messaging
objc_msgSend(receiver, selector, arg1, arg2, ...)
NSObject, NSProxy클래스로부터 상속받은 모든 클래스는 isa 변수(슈퍼클래스를 가리키는 포인터)와 dispatch table을 가진다.
dispatch table은 자신의 message name과 매칭되는 실제 함수 구현체의 포인터를 가지고 있는 map table이라고 보면된다.
objc_msgSend가 하는일은 receiver의 dispatch table에서 selector의 이름으로 함수 구현체를 찾고, 없으면 isa포인터를 통해 슈퍼클래스에 접근한 후 다시 dispatch table을 뒤진다.(이런식으로 recursive하게 root class까지 넘어간다.)
위 내용이 동적 바인딩이다.
Using hidden Arguments
objc_msgSend가 결국 메세지에 맞는 함수를 찾아서 호출해주는데 프로그래머가 메세지에 넘겨주는 파라미터 이외에 두개의 숨겨진 파라미터 2개를 같이 넘겨준다.
하나는 receiver, 하나는 selector이다.
Getting a Method Address
동적바인딩을 피하고 싶은경우, methodForSelector: 메서드를 사용해서 함수의 주소를 얻어와서 직접 함수를 call하면 된다. 하나의 메서드가 연속적으로 여러번 불려야 할경우 퍼포먼스를 조금이나마 개선하기 위해 해당 방식을 사용할 수 있다.
methodForSelector:은 런타임시스템에 의해 제공된다. Objective-C 언어가 제공하는것이 아니다.
Dynamic Method Resolutions
프로퍼티를 @dynamic 지시어를 지정하면 dynamic 메소드 콜을 할 수 있다.
예를들어 appdelegate의 window 프로퍼티를 dynamic 메소드 콜로 동작하게 하려면
UIWindow *dynamicMethodIMP(id self, SEL _cmd) {
return [[UIWindow alloc] initWithFrame:CGRectZero];
}
@dynamic window;
+ (BOOL)resolveInstanceMethod:(SEL)aSel
{
if (aSel == @selector(window))
{
class_addMethod([self class], aSel, (IMP)dynamicMethodIMP, "aaa");
return YES;
}
return [super resolveInstanceMethod:aSel];
}
이런식으로 구현 하면 됨. resolveClassMethod:를 사용하여 클래스 메소드도 dynamic 메소드 콜 적용 가능.
Dynamic Loading
NSBundle를 통해서 Objective-C 모듈을 동적으로 로딩할 수 있다.
'IOS > Objective-C' 카테고리의 다른 글
Naming Conventions (0) | 2017.02.18 |
---|---|
Block의 모든것(4) (0) | 2017.01.07 |
Block의 모든것(3) (0) | 2017.01.02 |
Block의 모든것(2) (0) | 2017.01.02 |
Block의 모든것(1) (0) | 2017.01.02 |