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
Posted by 홍성곤
,