27
Objective-C Runtime Programming Guide 리나소프트 13년 5월 21일 화

Objective-C Runtime Programming Guide

Embed Size (px)

DESCRIPTION

Objective-C Runtime Programming Guide 요약 자료입니다. Objective-C 런타임을 사용하면 성능을 향상 시킬수 있는 기법을 사용할 수 있습니다. 동적 바인딩이 속도면에서는 접고 들어가는거라 런타임 기능을 이해하면 좀 더 향상된 앱을 개발할 수 있지 않을까 합니다~~ 일부 다른 자료 참고했고, 이미지도 이모씨!!의 자료 사용했습니다~ㅋ

Citation preview

Page 1: Objective-C Runtime Programming Guide

Objective-C Runtime Programming Guide

리나소프트 김 성 관

13년 5월 21일 화

Page 2: Objective-C Runtime Programming Guide

✓ Objective-C 언어는 runtime 시에 많은 결정을 함.

✓ 컴파일된 코드를 실행하기 위해서는 컴파일러 뿐만 아니라 Runtime System이 필요함.

✓ Runtime System은 일종의 OS와 같이 동작.

- Objective-C 프로그램이 어떻게 runtime system과 상호작용하는지.

- 런타임시에 새로은 클래스를 어떻게 동적으로 로딩하는지.

- 다른 객체에게 어떻게 메시지를 전달하는지.

- 프로그램이 실행중인 동안 어떻게 객체에 대한 정보를 찾는지.

13년 5월 21일 화

Page 3: Objective-C Runtime Programming Guide

Interacting with the Runtime

Objective-C 프로그램은 3가지 레벨에서 런타임 시스템과 상호작용

1. Objective-C Source Code

2. NSObject Methods

3. Runtime Functions

13년 5월 21일 화

Page 4: Objective-C Runtime Programming Guide

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일 화

Page 5: Objective-C Runtime Programming Guide

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일 화

Page 6: Objective-C Runtime Programming Guide

Interacting with the Runtime

2. NSObject Methods

✓ Cocoa에서 대부분의 객체는 NSObject 클래스의 서브클래스

✓ 몇몇 메소드는 런타임 시스템에 간단한 질의 수행- 객체가 자신의 내부 정보를 획득(introspection)- class- isKindOfClass: , isMemberOfClass- respondsToSelectors:- conformsToProtocol:- methodForSelectors:

13년 5월 21일 화

Page 7: Objective-C Runtime Programming Guide

Interacting with the Runtime

3. Runtime Functions

✓ /usr/include/objc 에 있는 헤더 파일내의 데이터 구조나 함수의 조합

✓ 순수 C로 작성

✓ Objective-C 프로그래밍에는 필요하지 않음

✓ 런타임 시스템 인터페이스를 개발할 때 사용

13년 5월 21일 화

Page 8: Objective-C Runtime Programming Guide

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일 화

Page 9: Objective-C Runtime Programming Guide

Messaging

‣ 모든 클래스 객체는 다음 두 가지 항목을 포함하고 있다.

✓ superclass에 대한 포인터

✓ class dispatch table - selector와 함수 구현부의 주소를 연결

‣ 새로운 객체가 생성될 때 할당된 메모리와 인스턴스 변수들 초기화

‣ 객체의 변수들 중 첫번째는 클래스 구조에 대한 포인터 - isa 라고 부르를 포인터 - 클래스 자체와 클래스가 상속받은 모든 클래스에 대한 접근이 가능 - isa 포인터는 언어의 일부분이 아니지만, 런타임 시스템에서 동작하기 위해 필요

13년 5월 21일 화

Page 10: Objective-C Runtime Programming Guide

Messaging

함수가 동적으로 메소드에 바인딩 되는 과정

메시지가 객체에 전달

isa 포인터를 참조

dispatch table 검색

superclass 포인터를 참조

dispatch table 검색

cache 검색(MRU)

13년 5월 21일 화

Page 11: Objective-C Runtime Programming Guide

Using Hidden Arguments

✓ objc_msgSend가 procedure를 찾으면 호출하고, 메시지 내의 모든 인자를 전달

✓ 두개의 숨은 인자 - receiver - selector

✓ 메소드를 정의한 코드에 선언되어 있지 않기 때문에 “hidden argument”

✓ 코드가 컴파일 될 때 삽입

✓ 메소드는 수신 객체를 self로, 자신에 대한 selector를 _cmd로 참조

13년 5월 21일 화

Page 12: Objective-C Runtime Programming Guide

Using Hidden Arguments

- strange

{

id target = getTheReceiver();

SEL method = getTheMethod();

if ( target == self || method == _cmd )

return nil;

return [target performSelector:method];

}

13년 5월 21일 화

Page 13: Objective-C Runtime Programming Guide

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일 화

Page 14: Objective-C Runtime Programming Guide

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일 화

Page 15: Objective-C Runtime Programming Guide

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일 화

Page 16: Objective-C Runtime Programming Guide

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일 화

Page 17: Objective-C Runtime Programming Guide

Dynamic Loading

Objective-C 프로그램은 실행 중에 새로운 클래스와 카테고리를 로드하고 링크할 수 있다.

13년 5월 21일 화

Page 18: Objective-C Runtime Programming Guide

Message Forwarding

✓ 메시지 처리가 정의되어 있지 않은 객체에 메시지를 보내면 에러 발생

✓ 에러가 발생하기 전에 런타임 시스템은 메시지를 이해하고 있는 곳으로 메시지를 전달 ==> Message Forwarding

✓ NSInvocation 객체를 단일 인자로 하는 forwardInvocation 메시지 전달

-(void)forwardInvocation:(NSInvocation *) anInvocation

✓ 이 메소드는 NSObject에서 정의되어 있기 때문에 모든 객체에 사용할 수 있음.

✓ NSInvocation객체에는 target, selector, parameter 같이 메세지 송신에 필요한 모든 정보가 들어있음.

13년 5월 21일 화

Page 19: Objective-C Runtime Programming Guide

Message Forwarding

- negotiate {

if ( [someOtherObject respondsTo:@selector(negotiate)] )

return [someOtherObject negotiate];

return self;

}

13년 5월 21일 화

Page 20: Objective-C Runtime Programming Guide

Message Forwarding

- (void)forwardInvocation:(NSInvocation *)anInvocation {

if ([someOtherObject respondsToSelector: [anInvocation selector]])

[anInvocation invokeWithTarget:someOtherObject];

else

[super forwardInvocation:anInvocation];

}

- 동적인 방법으로 메시지 전달- 메시지 내의 selector와 일치하는 메소드가 없을 때 호출

- 원래 인자들과 함께 전달할 곳으로 보내야 함- 전달된 메시지의 리턴값은 원래 호출자에게 돌아감- 알 수 없는 메시지들을 서로 다른 수신자에게 배분하는 역할 (또는 모든 메시지를 같은 목적지로 보내는 역할)- 객체에 전달한 메시지가 존재할 경우 forwardInvocation은 호출되지 않음

13년 5월 21일 화

Page 21: Objective-C Runtime Programming Guide

Forwarding and Multiple Inheritance

✓ 포워딩은 다중 상속의 효과를 주는데 사용할 수 있다. (다중 상속에서 원하는 대부분의 기능을 제공)

✓ 메시지를 전달하는 객체는 receiver가 메시지를 처리하는 것 처럼 보이며, 값을 리턴 받는다.

13년 5월 21일 화

Page 22: Objective-C Runtime Programming Guide

Surrogate Object

✓ 다른 객체를 대신하고 메시지를 전달해주는 역할

✓ 크고, 무거운 동작을 수행하는 객체의 앞단에서 동작하는 객체 (경량 객체)

✓ 데이터에 관한 질의와 같은 간단한 처리는 직접 수행하고, 무거운 처리가 필요할 경우 실제 처리 객체에게 메시지 전달

✓ 커다란 객체로 향하는 모든 메시지는 surrogate를 통하게 되고, 다른 객체들은 두 객체를 동일하게 보게 됨

13년 5월 21일 화

Page 23: Objective-C Runtime Programming Guide

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일 화

Page 24: Objective-C Runtime Programming Guide

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일 화

Page 25: Objective-C Runtime Programming Guide

class object

isa

Class Object

instancevariable

instancemethodtable

metaclass object

isa

classmethodtable

NSObject

13년 5월 21일 화

Page 26: Objective-C Runtime Programming Guide

13년 5월 21일 화

Page 27: Objective-C Runtime Programming Guide

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일 화