2016-04-11 1 views
0

は、クラスメソッドとして初期化です:構文の他に、インスタンス化メソッドまたはクラスメソッドとして初期化メソッドを書くことに違いはありますか?ここ

+ (instancetype)imageEditorForDocument:(ImageDocument*)imageDocument 
{ 
    ImageEditorViewController* result = nil; 
    result = [[ImageEditorViewController alloc] initWithNibName:@"ImageEditorViewController" 
                 bundle:[NSBundle mainBundle]]; 

    if (result) 
    { 
     result.imageDocument = imageDocument; 
    } 
    return result; 
} 

そしてここでは、インスタンスメソッドとして初期化です:

- (instancetype)initWithDocument:(ImageDocument *)imageDocument 
{ 
    self = [[ImageEditorViewController alloc] initWithNibName:@"ImageEditorViewController" 
                 bundle:[NSBundle mainBundle]]; 

    if(self) 
    { 
     self.imageDocument = imageDocument; 
    } 
    return self; 
} 

は、私の知る限り、唯一の違いは、「送信者がdoesnのことですトンクラス初期化子

を使用しているときallocを呼び出す必要があります。しかし、他の理由があるのでしょうか?

また、サイドの質問にはクラスメソッドであるイニシャライザの名前がありますか?手動参照カウント(MRC)でNSColor

+ (NSColor *)colorWithRed:(CGFloat)red green:(CGFloat)green blue:(CGFloat)blue alpha:(CGFloat)alpha NS_AVAILABLE_MAC(10_9); 
+1

これはファクトリメソッドと呼ばれます。 – rmaddy

答えて

2

で 等は、差がインスタンスメソッドは、呼び出し側が現在所有しているインスタンスを返却しながらファクトリメソッドは、典型的には、自動解放インスタンスを戻しました。

自動参照カウント(ARC)では、その相違点が呼び出しコードから隠されるようになりました。

だから、唯一の違いは、オプションのファクトリメソッドを記述するために、クラスの作者の発信者の利便性だけでなく、少しより多くの仕事です。

BTW - インスタンスメソッドの初期化子が正しくありません。それより、この(selfを設定しないように適切な方法)のようにする必要があります:

- (instancetype)initWithDocument:(ImageDocument *)imageDocument 
{ 
    self = [super initWithNibName:@"ImageEditorViewController" 
          bundle:[NSBundle mainBundle]]; 

    if(self) 
    { 
     self.imageDocument = imageDocument; 
    } 

    return self; 
} 

そして、これを与え、あなたのファクトリメソッドが本当にする必要があります:

+ (instancetype)imageEditorForDocument:(ImageDocument*)imageDocument 
{ 
    ImageEditorViewController* result = [[[self class] alloc] initWithDocument:imageDocument]; 

    return result; 
} 
+0

ありがとうrmaddy :)そして間違ったコードで私の悪い私は実際にちょうどコピー貼り付けられたファクトメソッドとインスタンスの初期化のように見えるように変更 - しかし、その部分を見落とした。訂正ありがとう^^ –

+0

最新のアップデートをご覧ください。あなたの工場の方法も間違っていた。 – rmaddy

+0

インスタンスの初期化子は現在のコードには存在しません。 インスタンスイニシャライザメソッドを作成し、それを呼び出すようにファクトリメソッドを変更することをお勧めしますか? –

1

はい大きな違いがあります。ファクトリメソッド(クラスメソッド)を実装する場合、たとえば、新しいインスタンスを作成する代わりに、オブジェクトの既存のインスタンスを(たとえば、ある種のキャッシュから)返すことを選択できます。あなたが初期化するために高価なクラスCountryを持っていると想像してください。あなたは、「従来の」初期化子の呼び出し元を選択すると、一方

+(instancetype) countryForCountryCode: (NSString *)countryCode 
{ 
    Country *country = ... // ask our "CountryCache" if we already have a cached instance of the country 
    if (!country) { 
     country = [[Country alloc] init]; 
     // Here you would also set up the new Country object, or even write a "private" initializer 
     // You would also add the new instance to the cache here 
    } 
    return country; 
} 

:したがって、それは国が見つからない場合、それは新しいオブジェクトを作成し、最初で唯一のキャッシュを検索し、次のファクトリメソッドを書きますイニシャライザが呼び出される前に常にallocで新しいインスタンスが作成されるため、代わりにキャッシュされたオブジェクトを返す方法がありません。

最後に、私はちょうど私が永続オブジェクト(CoreDataを使用していない場合)に対処するたびに、私は個人的にファクトリメソッドを使用することを思い出しました。したがって、データベースから新しいオブジェクトを取得する場合は、通常、「ロード」というファクトリメソッドを実装します。そして実際にデータベースに新しいレコードを作成するために、 "create"という別のファクトリメソッドを実装します。ここでイニシャライザを使用すると、非常に混乱します。

+0

私は理解できません。 '[super init]を呼び出す前に、チェックができず、キャッシュされたオブジェクトがあればそれを返すだけですか? –

+0

私を止めるのは、インスタンスの初期化子呼び出し元が 'alloc'で作成した新しいインスタンスの中にすでに入っています。実際には' self'に他のオブジェクトを代入する必要がありますが、許可されていません。 – Lasse

+0

@AO私は私の答えをうまく編集しました私のポイントは今より明確になりました – Lasse

関連する問題