2013-03-09 4 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

「レイジー」は、2つの異なるコンテキストで使用されます。

クラスデザインを批評するとき、最初に、クラスは効果がない - その存在を正当化するのに十分ではないと主張します。人々はまた、この種のクラスを「薄い」と呼びます。 これはおそらくあなたがここで意味するものではありません。

第二に、遅延評価怠惰なインスタンス化クラスは唯一のプロパティを評価したり、実際に必要なときに自分自身を初期化する作業を行うことを意味します。

たとえば、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; 
} 

、我々はすべての彼らのレコードをルックアップする必要はありません!一方

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

、時には我々は彼らを必要とする:

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

我々だけisFounderを呼び出すために従業員を構築しているのであれば、我々はデータベース検索を無駄に。しかし、それをスキップすることはできません。paymentsが必要です。

私たちは、データベースの参照をコンストラクタから取り出し、loadメソッドに入れます。

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

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

従業員レコードは、実際に必要なときにのみ読み込まれます。それらが既にロードされている場合、私たちは余分な作業をしません(1つのメソッド呼び出しを除いて)。支払い記録が必要ない場合は、作業を一切行う必要はありません。

このクラスは、作業を行うために最後の1分を待つ必要があるときにのみ機能します。それは "怠け者!"

+0

答えてくれてありがとう、Mark。それが私の想像です。したがって、クラスはその動作のために「怠け者」とみなされます。でも、画像ファイルに非遅延として保存されているクラスをロードしていると思われる '_getObjc2NonlazyClassList'関数が存在することは、まだ気になります。コンパイル時にクラスを非遅延にする側面があるようです。画像ファイルからロードされたすべてのクラスは非遅延クラスとみなされます。 – LuisABOL

関連する問題