Upload
sung-kwan-kim
View
338
Download
7
Embed Size (px)
DESCRIPTION
Objective-C Runtime Programming Guide 요약 자료입니다. Objective-C 런타임을 사용하면 성능을 향상 시킬수 있는 기법을 사용할 수 있습니다. 동적 바인딩이 속도면에서는 접고 들어가는거라 런타임 기능을 이해하면 좀 더 향상된 앱을 개발할 수 있지 않을까 합니다~~ 일부 다른 자료 참고했고, 이미지도 이모씨!!의 자료 사용했습니다~ㅋ
Citation preview
Objective-C Runtime Programming Guide
리나소프트 김 성 관
13년 5월 21일 화
✓ Objective-C 언어는 runtime 시에 많은 결정을 함.
✓ 컴파일된 코드를 실행하기 위해서는 컴파일러 뿐만 아니라 Runtime System이 필요함.
✓ Runtime System은 일종의 OS와 같이 동작.
- Objective-C 프로그램이 어떻게 runtime system과 상호작용하는지.
- 런타임시에 새로은 클래스를 어떻게 동적으로 로딩하는지.
- 다른 객체에게 어떻게 메시지를 전달하는지.
- 프로그램이 실행중인 동안 어떻게 객체에 대한 정보를 찾는지.
13년 5월 21일 화
Interacting with the Runtime
Objective-C 프로그램은 3가지 레벨에서 런타임 시스템과 상호작용
1. Objective-C Source Code
2. NSObject Methods
3. Runtime Functions
13년 5월 21일 화
ClassC의 객체obj isa
stack Heap
Code
ClassC
-methodC
superClassB
-methodB
ClassAsuper
-methodA
NSObjectsuper
NSNumber
-methodX +alloc
NSNumber의 객체num
isa
super
-init -init+alloc
객체 생성 과정
13년 5월 21일 화
Interacting with the Runtime
1. Objective-C Source Code
✓ 런타임 시스템의 동작은 보이지 않는 곳에서 자동으로 동작
✓ Objective-C 소스코드를 작성하고 컴파일하게 되면 런타임 시스템을 간접적으로 사용
✓ 코드를 컴파일 하게 되면 data structure와 언어의 동적인 특성을 구현한 함수 호출을 만들어 냄
✓ Data Structure - Class와 Category 정의, Protocol 선언 정보 - method selector, instance variable templates, 그리고 소스 코드에서 추출된 다른 정보 등
13년 5월 21일 화
Interacting with the Runtime
2. NSObject Methods
✓ Cocoa에서 대부분의 객체는 NSObject 클래스의 서브클래스
✓ 몇몇 메소드는 런타임 시스템에 간단한 질의 수행- 객체가 자신의 내부 정보를 획득(introspection)- class- isKindOfClass: , isMemberOfClass- respondsToSelectors:- conformsToProtocol:- methodForSelectors:
13년 5월 21일 화
Interacting with the Runtime
3. Runtime Functions
✓ /usr/include/objc 에 있는 헤더 파일내의 데이터 구조나 함수의 조합
✓ 순수 C로 작성
✓ Objective-C 프로그래밍에는 필요하지 않음
✓ 런타임 시스템 인터페이스를 개발할 때 사용
13년 5월 21일 화
Messaging
Objective-C에서 메시지는 런타임까지 구현부에 바인딩 되지 않는다.
[receiver message] objc_msgSend(receiver, selector)
objc_msgSend(receiver, selector, arg1, arg2, ...)
✓ objc_msgSend(messaging function) 함수가 동적 바인딩에 필요한 모든 것을 수행. - selector가 참조하는 procedure(method implementation)를 찾는다. - 같은 함수가 다른 클래스에서 다르게 구현되어 있을 수 있기 때문에 정확한 procedure를 찾는 것은 receiver의 클래스에 달려있다. - receiving object에 데이터 포인터 전달, procedure 호출. - 처리 값 반환
✓ objc_msgSend 함수를 코드에서 직접 호출하면 안 됨!13년 5월 21일 화
Messaging
‣ 모든 클래스 객체는 다음 두 가지 항목을 포함하고 있다.
✓ superclass에 대한 포인터
✓ class dispatch table - selector와 함수 구현부의 주소를 연결
‣ 새로운 객체가 생성될 때 할당된 메모리와 인스턴스 변수들 초기화
‣ 객체의 변수들 중 첫번째는 클래스 구조에 대한 포인터 - isa 라고 부르를 포인터 - 클래스 자체와 클래스가 상속받은 모든 클래스에 대한 접근이 가능 - isa 포인터는 언어의 일부분이 아니지만, 런타임 시스템에서 동작하기 위해 필요
13년 5월 21일 화
Messaging
함수가 동적으로 메소드에 바인딩 되는 과정
메시지가 객체에 전달
isa 포인터를 참조
dispatch table 검색
superclass 포인터를 참조
dispatch table 검색
cache 검색(MRU)
13년 5월 21일 화
Using Hidden Arguments
✓ objc_msgSend가 procedure를 찾으면 호출하고, 메시지 내의 모든 인자를 전달
✓ 두개의 숨은 인자 - receiver - selector
✓ 메소드를 정의한 코드에 선언되어 있지 않기 때문에 “hidden argument”
✓ 코드가 컴파일 될 때 삽입
✓ 메소드는 수신 객체를 self로, 자신에 대한 selector를 _cmd로 참조
13년 5월 21일 화
Using Hidden Arguments
- strange
{
id target = getTheReceiver();
SEL method = getTheMethod();
if ( target == self || method == _cmd )
return nil;
return [target performSelector:method];
}
13년 5월 21일 화
Getting a Method Address
✓ 동적 바인딩을 회피하는 유일한 방법은 메소드의 주소를 얻어서 마치 함수인 것 처럼 직업 호출하는 방법 - 특정 메소드가 많은 횟수 반복적으로 사용될 때 매번 메시징 하는 오버헤드를 피하고 싶을 때 사용
✓ NSObject 클래스에 정의된 methodForSelector 사용 - procedure의 포인터 조회 - 포인터를 사용하여 procedure 호출 - 포인터는 알맞은 함수 타입으로 형변환 해야 함!
void (*setter)(id, SEL, BOOL);
int i;
setter = (void (*)(id, SEL, BOOL))[target methodForSelector:@selector(setFilled:)];
for ( i = 0; i < 1000; i++ )
setter(targetList[i], @selector(setFilled:), YES);
13년 5월 21일 화
Getting a Method Address
@interface MyClass : NSObject { }-(void)doSomething;@end
@implementation MyClass -(void) doSomething {
// Do many many work}@end
MyClass* myObject = [ [ MyClass alloc ] init ] ;
SEL method = @selector(doSomething) ; IMP func = [ myObject methodForSelector:method ] ; func( myObject, method );
13년 5월 21일 화
Dynamic Method Resolution
✓ 동적으로 메소드를 제공해야할 경우가 종종 있다.(?)
- @dynamic propertyName; - resolveInstanceMethod: - resolveClassMethod: - 주어진 selector에 대한 구현을 동적으로 제공
✓ Objective-C 메소드는 최소한 두개의 인자(self, _cmd)를 갖는 C 함수
✓ class_addMethod 함수를 사용하여 클래스에 함수를 메소드로 추가할 수 있음.
✓ Forwarding 메소드 또는 dynamic method resolution 둘 중 한가지 방법으로 동적 메소드 호출
✓ Forwarding 메커니즘을 시작하기 전에 dynamic method resolution 을 수행
13년 5월 21일 화
Dynamic Method Resolution
void dynamicMethodMP(id self, SEL _cmd) {
// implementation …
}
@implementation MyClass
+ (BOOL)resolveInstanceMethod:(SEL)aSEL {
if (aSEL == @selector(resolveThisMethodDynamically)) {
class_addMethod([self class], aSEL, (IMP) dynamicMethodIMP, “v@:”);
return YES;
}
return [super resolveInstanceMethod:aSEL];
}
@end
13년 5월 21일 화
Dynamic Loading
Objective-C 프로그램은 실행 중에 새로운 클래스와 카테고리를 로드하고 링크할 수 있다.
13년 5월 21일 화
Message Forwarding
✓ 메시지 처리가 정의되어 있지 않은 객체에 메시지를 보내면 에러 발생
✓ 에러가 발생하기 전에 런타임 시스템은 메시지를 이해하고 있는 곳으로 메시지를 전달 ==> Message Forwarding
✓ NSInvocation 객체를 단일 인자로 하는 forwardInvocation 메시지 전달
-(void)forwardInvocation:(NSInvocation *) anInvocation
✓ 이 메소드는 NSObject에서 정의되어 있기 때문에 모든 객체에 사용할 수 있음.
✓ NSInvocation객체에는 target, selector, parameter 같이 메세지 송신에 필요한 모든 정보가 들어있음.
13년 5월 21일 화
Message Forwarding
- negotiate {
if ( [someOtherObject respondsTo:@selector(negotiate)] )
return [someOtherObject negotiate];
return self;
}
13년 5월 21일 화
Message Forwarding
- (void)forwardInvocation:(NSInvocation *)anInvocation {
if ([someOtherObject respondsToSelector: [anInvocation selector]])
[anInvocation invokeWithTarget:someOtherObject];
else
[super forwardInvocation:anInvocation];
}
- 동적인 방법으로 메시지 전달- 메시지 내의 selector와 일치하는 메소드가 없을 때 호출
- 원래 인자들과 함께 전달할 곳으로 보내야 함- 전달된 메시지의 리턴값은 원래 호출자에게 돌아감- 알 수 없는 메시지들을 서로 다른 수신자에게 배분하는 역할 (또는 모든 메시지를 같은 목적지로 보내는 역할)- 객체에 전달한 메시지가 존재할 경우 forwardInvocation은 호출되지 않음
13년 5월 21일 화
Forwarding and Multiple Inheritance
✓ 포워딩은 다중 상속의 효과를 주는데 사용할 수 있다. (다중 상속에서 원하는 대부분의 기능을 제공)
✓ 메시지를 전달하는 객체는 receiver가 메시지를 처리하는 것 처럼 보이며, 값을 리턴 받는다.
13년 5월 21일 화
Surrogate Object
✓ 다른 객체를 대신하고 메시지를 전달해주는 역할
✓ 크고, 무거운 동작을 수행하는 객체의 앞단에서 동작하는 객체 (경량 객체)
✓ 데이터에 관한 질의와 같은 간단한 처리는 직접 수행하고, 무거운 처리가 필요할 경우 실제 처리 객체에게 메시지 전달
✓ 커다란 객체로 향하는 모든 메시지는 surrogate를 통하게 되고, 다른 객체들은 두 객체를 동일하게 보게 됨
13년 5월 21일 화
Forwarding and Inheritance
✓ 포워딩이 상속과 유사하게 보일지라도, respondsToSelector: , isKindOfClass: 같은 메소드는 forwarding chain을 고려하지 않는다.
✓ 만약 포워딩 객체가 실제 객체의 모든 행위를 상속 받은 것 처럼 사용하고 싶다면, 위 메소드를 오버라이딩 해야 한다.
(BOOL)respondsToSelector:(SEL)aSelector
{
if ( [super respondsToSelector:aSelector] ) return YES;
else { /* 이 부분에 aSelector 메시지가 *
* 다른 객체로 전달될 수 있는지 그리고 * * 해당 객체가 메시지에 응답할 수 있는지를 체크하고 *
* 그럴수 있다면 YES를 되돌리는 코드를 넣는다. */
}
return NO;
}
13년 5월 21일 화
Forwarding and Inheritance
✓ instancesRespondToSelector: , conformsToProtocol: 메소드 등도 필요에 따라 반영해야 한다.
✓ 객체가 원격지에서 수신한 모든 메시지를 전달한다면, methodSignatureForSelector: 메소드 구현해야 한다.
(NSMethodSignature*)methodSignatureForSelector:(SEL)selector
{
NSMethodSignature* signature = [super methodSignatureForSelector:selector];
if (!signature) {
signature = [surrogate methodSignatureForSelector:selector];
}
return signature;
}
13년 5월 21일 화
class object
isa
Class Object
instancevariable
instancemethodtable
metaclass object
isa
classmethodtable
NSObject
13년 5월 21일 화
13년 5월 21일 화
typedef struct objc_class *Class;
typedef struct objc_object { Class isa;} *id;
struct objc_class { Class isa;
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 }
runtime.h
typedef struct objc_method *Method;
struct objc_method { SEL method_name char *method_types IMP method_imp }
objc.h
13년 5월 21일 화