2

可変配列を含むディクショナリを作成するときのメモリ管理を理解するのに問題があります。展開ターゲット 5.1 で ios6 SDK を使用しています。

クラス "Group" の実装では、メソッド "namesAndEmails" が配列 "emails" を作成します。この配列には、電子メールを含む Person オブジェクトの電子メール アドレスが含まれます。Person オブジェクトに電子メールがない場合、Person 名が別の配列「namesWithNoEmail」に追加されます。配列はディクショナリで返されます。

#import "Group.h"
@implementation Group 

-(NSDictionary*) namesAndEmails {
    NSMutableArray  *emails = [[NSMutableArray alloc] initWithCapacity:0] ;
    NSMutableArray  *namesWithNoEmail = [[NSMutableArray alloc] initWithCapacity:0];
    NSString *email;
    NSString *name;
    for (Person *p in allPersons) {
        email = p.email;
        name = p.name;
        if ([email length]==0) {
            [namesWithNoEmail addObject:name];
        } else {
            [emails addObject:email];
        }
    }
    NSArray *keys = [NSArray arrayWithObjects:@"emails",@"names", nil];
    NSArray *objects = [NSArray arrayWithObjects:emails, namesWithNoEmail, nil];
    //[emails release];
    //[namesWithNoEmail release];

     return [NSDictionary dictionaryWithObjects:objects forKeys:keys];
}

コードのどこかでグループにメールを送信したいので、emailGroup メソッドを呼び出します。このメソッドは、グループで「namesAndEmails」を呼び出して辞書を取得します。

-(void) emailGroup:(Group*) g {

    NSDictionary *emailInfo = [g namesAndEmails];
    guestsWithNoEmail = [emailInfo objectForKey:@"names"];
    guestEmails = [emailInfo objectForKey:@"emails"];

   int nGuestsWithNoEmail = [guestsWithNoEmail count];

   if (nGuestsWithNoEmail > 0) {
      UIAlertView *alert = [[[UIAlertView alloc] initWithTitle:@"No emails" message:@"" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil] autorelease];
      [alert show];
   }

    // some more code here


    MFMailComposeViewController *picker = [[MFMailComposeViewController alloc] init];
    picker.mailComposeDelegate = self;
    [picker setSubject:subject];
    [picker setMessageBody:@"" isHTML:NO];
    [picker setToRecipients:guestEmails];
    [[self delegate ] presentModalViewController:picker animated:YES];
    [picker release];
}

私が理解している限り、「namesAndEmails」の [NSDictionary dictionaryWithObjects:objects forKeys:keys] は自動解放された辞書を返します。しかし、「emails」配列と「namesWithNoEmail」配列を解放すると、コードがクラッシュするのはなぜですか? 配列が追加された後、辞書は配列の所有権を持つため、メソッドで配列を解放しても安全だと思いました。それは正しくないと思いますが、なぜですか?

これを行うよりクリーンな方法はありますか?アドバイスありがとうございます!

4

1 に答える 1

2

私の最初の提案は、「製品->分析」機能を使用することです。どこかでリークしたり、過剰にリリースしたりすると、おそらく正確な一連のイベントが得られます。

nameAndEmails第二に、あなたのメソッドとの間のリンクが見えませんemailGroup:。接続が見えないため、自動解放が問題を引き起こしているかどうかはわかりません。

自動解放されたオブジェクトは、メインの実行ループが循環するときに解放されます。NSDictionaryしたがって、あなたが解放される可能性は非常に高いです。これは、デバッガーでメモリの場所を「ウォッチ」として設定することから、実行ループがサイクルするたびにコンソール行に何かを出力することまで、何でも行うことでテストできます (メインの実行ループであなたを仮定したので、修正してください)そうでない場合)。

問題を追跡するためにできる他のことは、インストゥルメントまたはNSZombieEnable=YES構成で「ゾンビ」を使用することです

于 2012-11-15T19:38:17.507 に答える