可変配列を含むディクショナリを作成するときのメモリ管理を理解するのに問題があります。展開ターゲット 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」配列を解放すると、コードがクラッシュするのはなぜですか? 配列が追加された後、辞書は配列の所有権を持つため、メソッドで配列を解放しても安全だと思いました。それは正しくないと思いますが、なぜですか?
これを行うよりクリーンな方法はありますか?アドバイスありがとうございます!