2013-08-02 2 views
1

Я пытаюсь сделать программу на контактах APP, используя адресную книгу, и она отлично работает, но когда я анализирую, есть несколько утечек памяти, мне удалось свести к минимуму утечки памяти, и теперь я дошел до 2 основных предупреждение утечки памяти, в моей адресной функции книги перегрузочной, я включил комментарии, чтобы показать, что все вещи, которые я пыталсяУстранение утечки памяти в Xcode

-(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"; 


} 

Другой утечка памяти в этом панели поиска функции

-(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); 
    }  

память шоу утечки on for loop statement и говорит:

+1

Чрезвычайно подозрительно похожий на этот вопрос: http://stackoverflow.com/questions/18010276/potential-memory-leak-abaddressbookcopyarrayofallpeople – borrrden

+0

Когда вы сказали, что «выделенный объект не сохранен [sic] в этом пути выполнения», вы имеете в виду «ссылки» или, возможно, «освобождены»? Нет причин для этого предлагать сохранить его, если у вас уже есть +1. (В общем, скопируйте и вставьте предупреждения из Navigator проблем, а не пытайтесь их перепечатать.) –

+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.

Вы говорите ARC взаимодействовать с CF миром через мост бросает:

  • __bridge_transfer (или CFBridgingRelease) говорит ARC «очистить эту собственность для меня, когда я сделал с ним».
  • __bridge_retained (или CFBridgingRetain) сообщает ARC «Я собираюсь выбросить этот объект в CF-land; не отпускайте его, пока я не скажу иначе »(который вы затем должны сделать в какой-то момент либо с переводом, либо с немедленным CFRelease).

И, опять же, вы вообще хотите вытащить вещи из мира CF и позволить ARC с ними справиться как можно больше.

Соответственно, я предлагаю сделать self.filteredData NSMutableArray, а не CFMutableArray. Создание массива с использованием Foundation означает, что он уже будет находиться под контролем ARC, без необходимости использовать его.

Для self.contactAdd вы можете перетащить его в NSArray, когда вы его извлечете, а затем обработайте его как NSArray с этого момента. Это включает в себя использование быстрого перечисления, а не индексации для его итерации, или, еще лучше, использование предикатного поиска вместо его итерации через него. (Я бы не рассчитывал на встроенный предикат сравнения, способный работать с ABPersons, но это то, за чем стоит predicateWithBlock:.)

Предикат версии вашего поискового кода будет выглядеть примерно так (крайне непроверенный) :

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

Я смог решить проблему, используя _addressbook вместо self.addressBook. Все проблемы ушли в xcode 4.6, но _addressbook, похоже, не работает на 4.2, но, возможно, версия для моста работает над этой версией. И для вашего другого вопроса, да, я уже сделали то же самое, используя ABPeoplePickerNavigationController, и это сработало хорошо, я просто хотел tr y это в другом методе с использованием CFArray. Спасибо за поддержку :) – Gamerlegend

0

Очевидно, вам не хватает [addContactButton release] в конце вашего viewDidLoad. Кроме того, почему звонки 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); разрешите одно предупреждение с помощью другой переменной вместе с этой функцией bridgerelease, но второе предупреждение все равно не исчезнет. – Gamerlegend

Смежные вопросы