2013-08-02 37 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); 
    }  

內存泄漏秀在for循環語句,它說:

+1

非常類似於這個問題:http://stackoverflow.com/questions/18010276/potential-memory-leak-abaddressbookcopyarrayofallpeople – borrrden

+0

當你說「分配的對象沒有保留在這個執行路徑中[sic]」,你是指「引用」還是「釋放」?如果您已經擁有+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的屬性。

你告訴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

我能夠解決通過使用self.addressBook的_addressbook不是問題。所有的問題走在Xcode 4.6,但_addressbook犯規似乎在4.2工作,但橋的釋放似乎對版本。而對於你的另一個問題,是我已經使用ABPeoplePickerNavigationController做了同樣的事情,它運行良好,我只是想要tr在另一種使用CFArray的方法中,感謝您的支持 :) – Gamerlegend

0

很明顯,您在viewDidLoad的末尾缺少[addContactButton release]。另外,爲什麼CFRelease的電話會被註釋掉?他們應該平衡CFArrayCreateMutable

關於self.contactAdd - 如果它被定義爲「retain」屬性,請不要直接爲其分配返回值ABAddressBookCopyArrayOfAllPeople。相反,實例化一個局部變量,其分配給屬性,然後使用CFRelease

+0

[addContactButton release]不是必需的,因爲它的ARC,即使我嘗試添加它,ARC也禁止它。如果添加了CFRelease,我會得到消息,該屬性返回+0保留計數的核心基礎對象。我曾嘗試ABAddressBookCopyArrayOfAllPeople的價值分配給另一個變量,並警告會消失,但我得到一個運行時錯誤:( – Gamerlegend

+0

對不起,你沒有提到ARC – Stavash

+0

self.contactAdd =(__ bridge_retained CFArrayRef)CFBridgingRelease(contactAddtemp);我能。解決另一個變量的幫助下,第一次警告,這個bridgerelease功能,但第二次警告仍犯規走沿 – Gamerlegend