2013-08-02 4 views
1

주소록을 사용하여 APP에 연락처 프로그램을 보내려고했지만 잘 작동하지만 메모리 누수가 몇 개있는 것으로 분석 할 때 메모리 누수를 최소화 할 수 있었고 현재는 2 개로 줄었습니다 메모리 누수 경고, 내 주소록 다시로드 기능의 하나는, 내가 또 다른 메모리 누수가이 검색 창 기능Xcode에서 메모리 누수 해결

-(void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText 
{ 

    if(searchText.length==0) 
    { 
     isFiltered=NO; 

    } 
    else 
    { 
     isFiltered=YES; 

     int j=0,i=0; 
     self.filteredData= CFArrayCreateMutable(kCFAllocatorDefault, 0,&kCFTypeArrayCallBacks);**// Memory warning here and says: call to function CFArrayCreateMutable returns a core foundation object with a +1 retain count** 

     for(i=0;i<CFArrayGetCount(self.contactAdd);i++)**//Memory warning here and says :object leaked :allocated object is not retained lated in this execution path and has retain count +1** 
     { 
      self.person=CFArrayGetValueAtIndex(self.contactAdd,i); 
      NSString *str=[[NSString stringWithFormat:@"%@", (__bridge_transfer NSString *)ABRecordCopyValue(self.person, kABPersonFirstNameProperty)] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]]; 
      NSRange contactRange= [str rangeOfString: searchText options:NSCaseInsensitiveSearch]; 

      NSLog(@"i=%d, j=%d",i,j); 

      if(contactRange.location!=NSNotFound) 
      { 
       CFArrayInsertValueAtIndex(self.filteredData,j++,self.person); 
       CFArrayGetValueAtIndex(self.filteredData,j-1); 
      } 

     } 
     //CFRelease(self.contactAdd); 
    //CFRelease(self.filteredData); 
    }  

메모리 누수 쇼에

-(void)reloadAddressBook 
{ 
    //if(self.addressBook) 
     //CFRelease(self.addressBook); 
    self.addressBook = (__bridge ABAddressBookRef) CFBridgingRelease(ABAddressBookCreate()); 

    if(ABAddressBookHasUnsavedChanges(self.addressBook)) 
    { 

     ABAddressBookSave(self.addressBook,NULL); 


    } 


    //if(self.contactAdd) 
     //CFRelease(self.contactAdd); 
    self.contactAdd= ABAddressBookCopyArrayOfAllPeople(self.addressBook); 


**//Memory warning here and says: call to function ABAddressBookCopyArrayOfAllPeople returns a core foundation object with a +1 retain count**  
     //self.contactAdd= (__bridge ABAddressBookRef) CFBridgingRelease(ABAddressBookCopyArrayOfAllPeople(self.addressBook)); 
     **// If I use this format my memory leak issue solves here but I get error in my program** 
    } 

- (void)viewDidLoad 
{**//Memory warning here and says :object leaked :allocated object is not retained lated in this execution path and has retain count +1** 
    [super viewDidLoad]; 

    self.contactSearchBar.delegate=self; 
    self.contactTableView.delegate=self; 
    self.contactTableView.dataSource=self; 

    UIBarButtonItem *addContactButton=[[UIBarButtonItem alloc]initWithTitle:@"Add" style:UIBarButtonItemStyleBordered target:self action:@selector(newContact:)]; 
    self.navigationItem.rightBarButtonItem=addContactButton; 
    [email protected]"My Contacts"; 


} 

시도할지 모든 것을 보여 주석을 포함했다 for 루프 문과 그것에 대해 말하기 :

+1

이 질문과 매우 유사합니다 : http://stackoverflow.com/questions/18010276/potential-memory-leak-abaddressbookcopyarrayofallpeople – borrrden

+0

"할당 된 객체가이 실행 경로에 저장되지 않았습니다"라고 말했을 때 당신은 "참조"또는 아마도 "발표"를 의미합니까? 이미 +1을 가지고 있다면 그것을 지킬 것을 제안 할 이유가 없습니다. (일반적으로, 이슈 탐색기에서 경고를 복사하여 붙여 넣기를 시도하는 대신 복사하십시오.) –

+0

"이 형식을 사용하면 메모리 누수 문제가 해결되지만 프로그램에 오류가 발생합니다"오류가 있습니까? –

답변

1

내가 my answer on your other question에서 언급처럼 사용하여 해제 한 다음, 그렇지 않으면 해당 등록 정보를 선언하지 않은 경우, 객체는 일반적으로 참조를 소유하고있다 개최 in Core Foundation, Create and Copy functions return an ownership reference.

속성을 로컬 변수를 인스턴스화 속성에 할당하고 weak).

self.filteredData= CFArrayCreateMutable(…); 

이제 두 번 객체를 소유 :이 같은 성명에서 것을 의미 당신이 그것을 만든, 한 번 당신의 속성을 유지하기 때문에 한 번 때문이다.

일반적으로 속성, ivar 또는 다른 강력한 참조 (예 : 로컬 변수)마다 각 개체를 한 번만 소유해야합니다. 추가 소유권 (예 : 만들기 및 복사 기능)은 정리해야 할 사항이므로 가능한 한 CF로 처리하는 것이 가장 좋습니다. ARC는 작업을 정리하지만 CF에 영향을주지 않습니다 네가 말하지 않으면 말야.

속성 및 로컬 변수에 대해 말하면 모든 것을 속성으로 만들 필요는 없습니다. 검색 코드의 person은 해당 메소드 내의 로컬 변수 여야합니다. 이는 해당 객체가 무한정 유지해야하는 것이 아니라 검색 상태의 일부이기 때문입니다. 이미 str을 로컬 변수로 사용하고 있으므로 person에 대한 속성을 사용하는 이유가 확실하지 않습니다.

당신은 다리를 통해 CF의 세계와 상호 작용하는 ARC에게 캐스트 :

  • __bridge_transfer (또는 CFBridgingRelease)는 "나는 그것으로 끝났어요 때 나를 위해이 소유권을 정리"ARC를 알려줍니다.
  • __bridge_retained (또는 CFBridgingRetain)은 ARC에게 다음과 같이 말합니다. "이 객체를 CF 랜드에 던질 것입니다. 내가 달리 말할 때까지 그걸 놓아 두지 마라. "(어느 지점에서 전송이나 즉시 CFRelease)해야합니다.

그리고 일반적으로 CF 세계에서 벗어나고 ARC가 가능한 한 많이 처리하도록하고 싶습니다.

따라서을 CFMutableArray가 아닌 NSMutableArray로 만들 것을 제안합니다. 파운데이션을 사용하여 어레이를 생성한다는 것은 브리지 캐스팅 할 필요없이 이미 ARC가 제어 할 수 있음을 의미합니다.

self.contactAdd의 경우 브리지 검색 할 때 NSArray로 브릿 캐스팅 한 다음 NSArray로 처리 할 수 ​​있습니다. 여기에는 빠른 열거 형을 사용하여 인덱싱을 반복하는 대신 인덱싱을 사용하는 것이 포함되며, 더 나은 방법은 직접 반복하는 대신 조건부 검색을 사용하는 것입니다. (나는 ABPerson과 함께 작업 할 수있는 내장 된 비교 술어에 의존하지 않을 것이지만, 그것은 을위한 것이다.)

검색 코드의 술어 기반 버전은 다음과 같이 보일 것이다. :

self.filteredData = [self.contactAdd filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(id evaluatedObject, NSDictionary *bindings){ 
    ABPersonRef person = (__bridge ABPersonRef)evaluatedObject; 
    NSString *firstName = [[NSString stringWithFormat:@"%@", (__bridge_transfer NSString *)ABRecordCopyValue(self.person, kABPersonFirstNameProperty)] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]]; 

    NSRange contactRange = [str rangeOfString:searchText options:NSCaseInsensitiveSearch]; 
    return (contactRange.location != NSNotFound); 
}]; 

(블록, 그리고 기초 술어는 각 객체와 일치하는지 여부를 반환 filteredArrayUsingPredicate: 술어가 true을 평가하는 모든 객체를 포함하는 배열을 생성한다.).

한가지 더 : ABPeoplePickerNavigationControll 사용을 고려 했습니까? 그렇지?

+0

self.addressBook 대신 _addressbook을 사용하여 문제를 해결할 수 있었지만 모든 문제는 xcode 4.6에서 사라졌지만 _addressbook doesnt는 4.2에서 작동하지만 브리지 릴리즈는 해당 버전에서 작동하는 것으로 보입니다. 이미 ABPeoplePickerNavigationController를 사용하여 동일한 작업을 수행했으며 제대로 작동 했으므로 tr 이 방법은 CFArray를 사용하는 다른 방법입니다. 귀하의 지원에 감사드립니다 :) – Gamerlegend

0

분명히 viewDidLoad의 끝에 [addContactButton release]이 누락되었습니다. 또한 CFRelease 호출이 주석 처리 된 이유는 무엇입니까? 그들은 균형을 유지해야합니다 CFArrayCreateMutable

self.contactAdd - "보유"속성으로 정의 된 경우 ABAddressBookCopyArrayOfAllPeople의 반환 값을 직접 할당하지 마십시오. 대신, 보통 (CFRelease

+0

[addContactButton release]는 ARC가 필요하기 때문에 필요하지 않습니다. 추가하려고해도 ARC는이를 금지합니다. 그리고 CFRelease가 추가되면 그 속성이 +0 유지 카운트를 가진 핵심 기초 개체를 반환한다는 메시지가 나타납니다. 나는 ABAddressBookCopyArrayOfAllPeople의 값을 다른 변수에 할당하려고 시도했지만 경고는 사라지지만 런타임 오류가 발생합니다. ( – Gamerlegend

+0

죄송합니다. ARC – Stavash

+0

self.contactAdd = (__ bridge_retained CFArrayRef) CFBridgingRelease (contactAddtemp); 이 변수와 함께 다른 변수의 도움으로 첫 번째 경고를 해결하지만 두 번째 경고는 여전히 사라지지 않습니다. – Gamerlegend