2013-03-09 3 views
9

Objective-C 런타임 라이브러리 소스 코드에서 특히 objc-runtime-new.mm을 보면 게으른 클래스와 비 게으른 클래스를 언급하는 몇 가지 기능과 주석을 보았습니다. +load 메서드가없는 클래스는 지연 클래스라고 불리는 것 같지만, 확실하지는 않지만 올바르지 않을 가능성이 큽니다. Google에서 검색 한 후 Objective-C의 게으른 클래스에 관해서 아무 것도 발견하지 못했습니다.Objective-C : 게으른 클래스 란 무엇입니까?

그래서 Objective-C의 게으른 클래스 란 무엇입니까? Obj-C에는이 기능이 있습니까? 클래스 구현시 +load 메서드가 있는지 여부와 관련이 있습니까? 위에 링크 된 파일에서 런타임 시스템은 _getObjc2NonlazyClassList이라는 함수를 호출하여 이미지에서 비 게으른 클래스의 목록을 가져옵니다. _getObjc2LazyClassList 기능이없는 이유는 무엇입니까?

+0

은 플러그인에서로드 된 클래스 일 수 있습니다. 어쩌면 플러그인/dyld/동적으로로드 된 코드에 대한 설명서를 확인하십시오 – nielsbot

+0

클래스가 게으른 것이 아니라 목록이라는 것을 확신합니까? –

+0

@JoshCaswell과 동의합니다. 나중에 런타임 소스에서 클래스에 지연로드에 대한 참조가 있음을 감안할 때. 클래스가 '게으른'것이 라기보다 거의 확실히리스트를 참조합니다. – lxt

답변

11

나는 대답을 찾았습니다 : 그것은 모두 구현하는 클래스에 관한 것이거나 +load 메소드가 아닙니다.

주어진 이미지 파일에 구현 된 모든 클래스는 "__DATA, __objc_classlist, regular, no_dead_strip" 바이너리 섹션에 저장된 목록의 참조를 갖습니다.이 목록은 런타임 시스템이 해당 파일에 저장된 모든 클래스를 추적 할 수있게합니다. 그러나 프로그램이 시작될 때 모든 클래스가 실현 될 필요는 없습니다. 따라서 클래스가 +load 메소드를 구현할 때 "__DATA, __objc_nlclslist, regular, no_dead_strip" 섹션에 저장된 목록에 참조가 있습니다.

따라서 _getObjc2NonlazyClassList+load 메서드를 구현하는 클래스 목록을 검색하며이를 '게으른'이라고합니다. _getObjc2ClassList+load 메소드가없고 (게으른이라고 부르는) 클래스와 비 게으른 클래스를 포함하여 이미지 파일의 모든 클래스 목록을 검색합니다. 프로그램이 시작될 때 비 게으름 클래스가 실현되어야합니다. 반면, 게으른 수업은 즉시 실현 될 필요가 없습니다. 예를 들어, 수업이 처음으로 메시지를 수신 할 때까지 지연 될 수 있습니다 (이는 그것이 "게으른"것으로 간주되는 이유입니다).

그런데 카테고리에 대해서도 마찬가지입니다.

+0

범주에 대해 해당 범주가 외부 라이브러리에있는 경우 링커 플래그'all_load'를 사용해야합니다. –

+0

이것은 거의 정확할 수 있지만 __objc_nlclslist가 포함 된 MachO 이미지를 보았지만 __objc_classlist 섹션은 포함하지 않았습니다. – jsears

5

"지연"은 서로 다른 두 가지 상황에서 사용됩니다.

클래스 디자인을 비판 할 때, 클래스가 효과가 없다고 주장합니다. 클래스의 존재를 정당화하기에는 충분하지 않습니다. 사람들은 또한 이런 종류의 클래스를 "얇은"이라고 부릅니다. 이것은 아마 여기에있는 것이 아닙니다.

둘째, 게으른 평가게으른 인스턴스이 클래스는 속성을 평가하거나 실제로 필요할 때 자체를 초기화하는 작업을 수행 것을 의미한다.

예를 들어 Employee 객체를 만드는 클래스가 있다고 가정합니다.

@implementation Employee 
- (id) initWithID: (IdentificationCode*) ident 
{ 
    self =[super init] 
    if (self) { 
     _records=[self retrieveEmployeeRecordsFor: ident]; 
     _identification=ident; 
     } 
    return self; 
} 

데이터베이스에서 모든 레코드를 검색하는 속도가 느릴 수 있습니다. 그리고 때때로 우리는 그 일을 할 필요가 없습니다. 예를 들면 :

- (BOOL) isFounder 
{ 
    if (indent.number<10) return YES; 
    return NO; 
} 

우리는 직원을 인스턴스화하는 경우 단순히 그들이 창립자 인 경우, 우리는 모두 자신의 기록을 찾아 볼 필요가 없습니다 찾으려면! 우리가 isFounder를 호출하는 직원을 구성하는 경우

- (NSArray*) payments 
{ 
    return [self.records retrievePayStubs]; 
    } 

그래서, 우리는 데이터베이스 조회를 낭비 : 한편

..... 
if ([thisEmployee isFounder]) { 
     [self sendCandyTo: thisEmployee.identification]; 
     } 

때때로 우리는 그들을 필요합니다. 하지만 payments에 필요하기 때문에 건너 뛸 수 없습니다.

우리가하는 일은 생성자에서 데이터베이스 검색을 가져 와서 load 메서드에 넣는 것입니다.

- (void) load 
{ 
    if (records) return; 
    self.records=[self retrieveEmployeeRecordsFor: ident]; 
} 

- (NSArray*) payments 
{ 
    [self load]; 
    return [self.records retrievePayStubs]; 
    } 

이제 우리는 직원 기록을 실제로 필요할 때만로드합니다. 이미로드 된 경우 별도의 메소드 작업을 수행하지 않습니다. 지불 기록이 필요 없다면, 우리는 일을 전혀 할 필요가 없습니다.

클래스는 작업을 수행하는 데 마지막 순간까지 기다려야 만 작동합니다. 그것은 "게으르다!"

+0

답해 주셔서 감사합니다, 마크. 그것이 내가 상상 한 것입니다. 따라서 클래스는 동작 때문에 '게으른 클래스'로 간주됩니다. 그러나 뭔가가 여전히 귀찮다 : 이미지 파일에 non-lazy로 저장된 클래스를로드하는 것처럼 보이는'_getObjc2NonlazyClassList' 함수의 존재. 컴파일 할 때 클래스를 게으르지 않게 만드는 측면이 있습니다. 아니면 단지 명명법 일뿐입니다. 이미지 파일에서로드 된 모든 클래스는 비 게으름으로 간주됩니다 ... – LuisABOL