2

私が見ている機能:

-(void)viewDidLoad {
    NSBundle *bundle = [NSBundle mainBundle];
    NSString *plistPath = [bundle pathForResource:@"statedictionary" ofType:@"plist"];

    NSDictionary *dictionary = [[NSDictionary alloc] initWithContentsOfFile:plistPath];
    self.statesZips = dictionary;
    [dictionary release];

    NSArray *components = [self.stateZips allKeys];
    NSArray *sorted = [components sortedArrayUsingSelector:@selector(compare:)];
    self.States = sorted;

    NSString *selectedState = [self.states objectAtIndex:0];
    NSArray *array = [stateZips objectForKey: selectedState];
    self.zips = array;  
}

NSDictionary が割り当てられ、次に *dictionary というポインターに割り当てられ、次にインスタンス変数 stateZips に割り当てられるのはなぜですか? それを割り当ててインスタンス変数に直接割り当て、別の NSDictionary の作成と解放のメモリを節約してみませんか? NSArray を使用したこの関数の後半を含め、常に同じ方法論に従います...

NSDictionary *dictionary = [[NSDictionary alloc] initWithContentsOfFile:plistPath];
self.statesZips = dictionary;
[dictionary release];

また、このソートでは、ハッシュ テーブル (辞書) のキーがアルファベット順に並べられます。この行を理解しているかどうかわかりません:

NSArray *sorted = [components sortedArrayUsingSelector:@selector(compare:)];
4

3 に答える 3

6

という事実に誰も対処していないようです。

self.statesZips = dictionary;

直接のインスタンス変数の代入ではありません。stateZipsはプロパティであるため、そのコード行はsetStateZips:メソッドを呼び出します。そのメソッドはディクショナリを保持またはコピーするため、メソッドが何らかの目的でディクショナリを再度使用する予定がない限り、ディクショナリviewDidLoadは不要になります。それはそれでOKですrelease

前の行:

[[NSDictionary alloc] initWithContentsOfFile:plistPath];

オブジェクトを割り当てます。release必要がなくなったら、それはあなたの責任になります。プロパティに割り当てた後はstatesZips不要になるため、解放されます。使用しdictionaryないでください。self.stateZips後のコードでは、ではなくのみを参照していることに気付くでしょうdictionary

NSArrayメソッドの後半の場合viewDidLoad、オブジェクトを割り当てないため、そのメソッドはそれを呼び出す責任がありませんrelease。経験則では、allocそれがリリースされたことを確認する責任があります。そうでなければ、それはあなたの問題ではありません。

配列のソートはsortedArrayUsingSelector:メソッドを使用します。セレクターは、Objective-C のメソッドを識別します。そして、これ@selectorはセレクターの@""リテラル構文です (オブジェクトのリテラル構文と似ていNSStringます)。したがって、そのコードは、「オブジェクトcomponentsがソートされている配列を与えて、compare:ソートを行うときにメソッドを使用して各オブジェクトを比較します。配列をソートすると、compare:配列内のオブジェクトを呼び出してそれらをどのように並べるかを決定します。

于 2009-03-25T21:47:10.183 に答える
4

プロパティはおそらく保持されstatesZipsます、それが理由です。

NSDictionary が最初に割り当てられるとき、その保持カウントは 1 です。statesZips に割り当てられると、保持カウントは 2 になります。解放されると、保持カウントは 1 に下がります。これは通常、望ましい結果です。

以下のコードは (ほぼ) 同じ結果になることに注意してください。

self.statesZips = [NSDictionary dictionaryWithContentsOfFile:plistPath];

dictionaryWithContentsOfFile自動解放されたオブジェクトを返すためです。

慣例として、通常の alloc-init メソッド (のように) は保持されたオブジェクトを返しますが、クラス メソッドは[NSDictionary dictionary]自動解放されたオブジェクト (しばらくすると自動的に解放されます) を返します。[[NSDictionary alloc] init]

詳細については、Cocoa のメモリ管理プログラミング ガイドをお読みになることをお勧めします。

編集:最初に読んだとき、あなたの質問の最後の部分を見逃していたに違いありませんが、Barry はすでにその部分に答えています。

于 2009-03-25T21:03:04.877 に答える
2

このコードは、参照カウント メモリ管理を使用します (OS X 上の Objective-C 2.0 で利用可能な自動ガベージ コレクション メモリ管理ではありません)。いずれかのオブジェクト (この場合は NSDictionary と NSArray) が割り当てられると、呼び出し元は-releaseそのインスタンスを呼び出す責任があります。release の呼び出しに失敗すると、メモリ リークが発生します。コードは次のように記述できます。

self.statesZips = [[[NSDictionary alloc] initWithContentsOfFile:plistPath] autorelease];

ただし、メモリ管理の明示性が低くなります (NSAutoreleasePoolイベント ループの反復の最後に割り当てられたインスタンスを解放することに依存します)。

呼び出し

[components sortedArrayUsingSelector:@selector(compare:)];

components[elem1 compare:elem2] を呼び出して 2 つの配列要素を比較した場合の戻り値に従って、要素の配列を返します。

于 2009-03-25T21:03:22.100 に答える