0

以下の私のプロジェクトにある実際の例があります。私の目的は、SMS受信用の最も可能性の高い電話番号と、その(電話)番号のみを選択することです。最後にメモリを解放しない場合はすべてうまく機能しますが、それを実現することはできません。私の質問は次のとおりです。以下の例でメモリを解放する正しい方法はどこ(およびどのように)ですか?

// Called after a person has been selected by the user. Return YES if you want the person to be displayed.
// Return NO to do nothing (the delegate is responsible for dismissing the peoplepicker)
- (BOOL) peoplePickerNavigationController: (ABPeoplePickerNavigationController *) peoplePicker 
    shouldContinueAfterSelectingPerson: (ABRecordRef)person
{     
 // Retrieving the person's most likely phonenumber (kABPersonPhoneProperty)
 CFStringRef phoneNumber, phoneNumberLabel;

 ABMutableMultiValueRef multiValueReference = ABMultiValueCreateMutable(kABMultiStringPropertyType); 
 multiValueReference = ABRecordCopyValue(person, kABPersonPhoneProperty);

 NSMutableString *mostLikelyPhoneNumber = [[NSMutableString alloc] init];

 // Iterating through all the phone numbers in the list
 for (CFIndex i = 0; i < ABMultiValueGetCount(multiValueReference); i++) {

  phoneNumberLabel = ABMultiValueCopyLabelAtIndex(multiValueReference, i);
  phoneNumber      = ABMultiValueCopyValueAtIndex(multiValueReference, i);

  // Converting to NSString for easier comparison (this way I have only NSStrings)
  NSString *NSStringphoneNumberLabel =  [[NSString alloc] init];
  NSString *NSStringphoneNumber =  [[NSString alloc] init];

  // Copying the contents of the CFStringRef to my NSString pointers
  NSStringphoneNumberLabel = (NSString *) phoneNumberLabel;
  NSStringphoneNumber = (NSString *) phoneNumber;

  LOG (@"Phone number: %@/%@", phoneNumberLabel, phoneNumber); // No problem so far!
  LOG (@"Phone number: %@/%@", NSStringphoneNumberLabel, NSStringphoneNumber); // No problem so far!

  // If this phone number has a "iphone" or a "mobile" label, save it to mostLikelyPhoneNumber
  if ([NSStringphoneNumberLabel isEqualToString:@"_$!<Mobile>!$_"]) 
  {
   mostLikelyPhoneNumber = (NSMutableString *) NSStringphoneNumber;
  }

  else if ([NSStringphoneNumberLabel isEqualToString:@"iPhone"])
  {
   mostLikelyPhoneNumber = (NSMutableString *) NSStringphoneNumber;
   // However, if it was an "iphone", break out of the loop. (Can't get any better than iPhone)
   break; 
  }

  _tfGSM.text = (NSString*) mostLikelyPhoneNumber;

  // Releasing memory used in this particular iteration
  [NSStringphoneNumber release];
  [NSStringphoneNumberLabel release];  
 }

 // Releasing rest of memory  THIS IS WHERE IT CRASHES!
 [mostLikelyPhoneNumber release];
 CFRelease(phoneNumberLabel); 
 CFRelease(phoneNumber); 
 CFRelease(multiValueReference);

 [self dismissModalViewControllerAnimated:YES];
 return NO; // As soon as a person is picked, we end this address book sidetrip and return to the app
}
4

1 に答える 1

1

=あなたの基本的な問題は、何を意味するのか理解していないようです。

このランダムに選択された例のように、あるポインタ値を別のポインタ値に割り当てる場合:

mostLikelyPhoneNumber = (NSMutableString*) NSStringphoneNumber;

2番目の文字列の内容を変更可能な最初の文字列にコピーしていません。むしろ、ポインタ自体を上書きしています。NSMutableStringしたがって、以前に割り当てた元のポインタは失われ、所有していないNSStringphoneNumber値への2番目の参照しかありません。

コードのどこでもほとんど同じことをします。

最終的にクリーンアップを希望する場合、割り当てられたオブジェクトへのポインタがなくなったため、クリーンアップできません。試してみると、代わりに、所有していないものを大量にリリースしすぎて、クラッシュが発生します。

通常、これらの状況では、メモリ管理ガイドにアクセスして読むことをお勧めしますが、率直に言って、基本に戻って、最初に修復Cを実行する方がよいと思います。

于 2010-07-30T09:05:05.663 に答える