2011-09-27 7 views
0

UIImage APIリファレンスドキュメント:
initWithContentsOfFile:
指定されたファイルの内容を持つイメージオブジェクトを初期化して返します。iOS - ここでどのようにメモリが処理されているのですか?

- (id)initWithContentsOfFile:(NSString *)path 

パラメータ
パス
ファイルへのパス。このパスには、イメージデータの種類を識別するファイル名拡張子を含める必要があります。この方法は、ファイルを見つけるか、その内容から画像を初期化できませんでした場合
戻り値 AnがUIImageオブジェクト、またはゼロを初期化します。このシナリオを考慮


、私はクラスがあると、それがどのクラスの拡張である可能性があります。ちょうど例えばUIImageを取った。今

@interface myImage : UIImage 
{ 
    BOOL isDefaultSet; 
} 

-(id)initWithDefaultImage; 

@end 

@implementation myImage 


-(id)initWithDefaultImage 
{ 
    NSString *path = [[NSBundle mainBundle] pathForResource:@"someInvalidImage" ofType:@"png"]; 

    idDefaultSet = YES; 

    return [self initWithContentsOfFile:path]; 
} 

@end 


//somewhere in other class: 

NSString *path = [[NSBundle mainBundle] pathForResource:@"someInvalidImage" ofType:@"png"]; 

myImage *myObject = [[myImage alloc] initWithDefaultImage]; 
UIImage *yourObject = [[UIImage alloc] initWithContentsOfFile:path]; 

ここでどちらの場合も、

"アロケーションは、" "retainCount + 1"

と返さ

initWithDefaultImage/initWithContentsOfFile

場合を与えます原因はありませんいくつかの問題 - 。(無効なファイルのパスを)言うことができますが、このメモリは

myObjectという/ yourObject

としてリークされます割り当てが初期化前に行われたにもかかわらず、nilに設定されます。

私は、このように拡張クラス/インタフェースの多くの実装を見てきました。私はメモリがここでどのように扱われているのか混乱していますか?誰もこれについての見解を共有できますか?

+0

慣例に従い、クラスを大文字で始めることを提案します。あなたはあなたの人生をより楽にしてくれるでしょう(もしあなたが他の人と働いているなら、あなたは侮辱されて殴られることを避けます;-) – DarkDust

+0

親愛なるダークダスト..私はこの問題について議論しています。あまりにも厳しくはありません..! – samfisher

+0

ダークダストが冗談を言っていたと思う。 DarkDustは正しいですが、私は難しい方法を学んだので、クラスは大文字にする必要があります。ivarsとメソッドは小文字で始まります。 – johnbakers

答えて

1

[super init]がnilを返す場合、nilが返されます。そのメソッドから制御が戻ると[super init]戻りnilは、スーパーのinitが既に自体後に洗浄している場合は、「initWithFoo」

を呼び出す前に(someInitializingFailed)ブロックが実行されることはありませんし、メモリがすでに実行されたのallocとして漏洩するかどうとallocによって割り当てられたメモリを解放しました。 Handling Initialization Failureから

あなただけの障害が発生した時点で、自己のリリースメソッドを呼び出す必要があります。スーパークラスの初期化子の呼び出しからnilを返す場合は、releaseを呼び出すべきではありません。

0

あなたは正しいですが、時々人々はこの漏れを処理することを忘れてしまいます。初期化を続行できない場合は、割り当てられたメモリを解放する必要があります。

-(id)initWithDefaultImage 
{ 
    NSString *path = [[NSBundle mainBundle] pathForResource:@"someInvalidImage" ofType:@"png"]; 
    if (path != nil) 
    { 
     self = [super initWithContentsOfFile:path]; 
    } 
    else // cannot proceed with init 
    { 
     [self release]; 
     self = nil; 
    } 
    return self; 
} 
+0

最初にinitを済ませたら、どうやってinitWithContentsOfFileを呼び出すことができますか? – samfisher

+0

良い点。私はコードを更新しました。 – Davyd

1

通常のように、nilを返す前に、対応する初期化子リリースself(新しいオブジェクト):

- (id)initWithFoo 
{ 
    self = [super init]; 
    if (!self) return nil; 

    if (someInitializingFailed) { 
     [self release]; 
     return nil; 
    } 

    return self; 
} 

あなたは-[UIImage initWithContentsOfFile:]は、同じパターンを実装していると仮定することができます。インストゥルメントがあなたに漏れがあることを伝えていない限り、あなたのケースで特別な取り扱いをする必要はありません。

+0

この場合も参照してください。 [super init]がnilを返すと、nilが返されます。したがって、 "initWithFoo"を呼び出す前に、メソッドとif(someInitializingFailed)ブロックが決して実行されず、allocが既に実行されているのでメモリがリークします。 – samfisher

+0

- > [self initWithContentsOfFile:path];を返します。 - >を返す[super initWithContentsOfFile:path];それは正しいでしょうか? – samfisher

+2

@samfisher '[super init]'が 'nil'を返す場合、スーパーの' init'はすでにそれ自身の後でクリーンアップされ、 'alloc'によって割り当てられたメモリを解放しました。 [言い換えれば](http://developer.apple.com/library/ios/DOCUMENTATION/Cocoa/Conceptual/ObjectiveC/Chapters/ocAllocInit.html#//apple_ref/doc/uid/TP30001163-CH22-SW13)で、失敗した時点でのみreleaseメソッドをselfで呼び出す必要があります。スーパークラスの初期化子の呼び出しからnilが返された場合は、releaseを呼び出すべきではありません。 – albertamg

関連する問題