2010년 9월 12일 일요일

object-c objc_msgSend

NSObject는 isa라는 인스턴스 변수를 갖는다. 이 isa는 객체를 생성하는 클래스구조체를 가리키는 포인터이다.
isa가 가르키는 클래스 구조체는 클래스의 인스턴스 변수, 유형과 이름, class method의 구현, super class의 클래스구조체를 가르키는 포인터 등으로 구성된다.

'selector'는 이 클래스의 method를 색인 한다. selector는 SEL의 유형을 갖는데, 이는 실제로 char*로 대응된다. (typedef SEL char* 의 의미인듯)
이 selector는 각 method의 고유한 정수값으로 되어 있다.
이것이 메시지와 갖는 연관성은 다음과 같다.
컴파일 시에 컴파일러는 메시지를 보내야 할 때마다 selector를 찾는다.

예 addObject의 selector가 12라고 가정하면
[myObject addObjet:yourObject];
objc_msgSend(myObject, 12, yourObject);

objc_msgSend()는 myObject의 isa포인터에서 클래스 구조체를 가져온다. 그후 클래스 구조체에서 12에 연결된 method를 찾는다. (해당클래스에 method가 없으면 상위의super class에거 찾는다.




[receiver message]와 같은 구문이 있을때 이 메시지 호출은 objc_msgSend(receiver, selector)메시징 함수로 바뀌어 불리게 된다.

함수형
id objc_msgSend(id theReceiver, SEL theSelector, ...)

파라메터
theReceiver : 메시지를 받게되는 클래스 인스턴스 포인터
theSelector : 호출하고자 하는 클래스 메서드
   ...      : 메서드의 전달 인자 리스트

ReturnValue(id) : 메서드 리턴값

위 함수에서 첫번째 파라메터 id는 구조체이다. 이것은 아래와 같은 형식을 가지고 있다.
typedef struct objc_object
{
    Class isa;
} *id;

typedef struct objc_class *Class;

struct objc_class
{
   struct objc_class* isa;
   struct objc_class* super_class;
   const char* name;
   long version;
   long info;
   long instance_size;
   struct objc_ivar_list* ivars;
   struct objc_method_list** methodLists;
   struct objc_cache* cache;
   struct objc_protocol_list* protocols;
};
위와 같이 id는 objc_class 구조체의 인스턴스 포인터 변수일 뿐이다.
구조체의 내부를 들여다 보자.

isa는 클래스 정의 포인터를 가진다.(뭔지 잘 모르겠다.)
super_class는 base 클래스의 pointer를 가진다.
Name
Version
Info
Instance_size
Ivars
methodLists;
cache
protocols