2012-06-24 65 views
3

在我的應用程序中,我必須檢索用戶聯繫人的某些屬性。例如,我需要檢索聯繫人的名字,姓氏,中間名,暱稱,組織,職位,部門,生日,電子郵件等。我有一些方法來檢索這些屬性,並且只有幾個工作,即使他們都非常相似。這裏是我的一個方法,在工作(名字)和一個代碼,沒有(職務):ABRecordCopyValue()EXC_BAD_ACCESS錯誤

+(NSString *)fetchFirstnameForPersonID: (NSUInteger)identifier{ 

    NSString *firstName; 
    ABRecordRef currentPerson = (__bridge ABRecordRef)[[PSAddressBook arrayOfContacts] objectAtIndex:identifier]; 

    //If the first name property exists 
    if ((__bridge_transfer NSString *)ABRecordCopyValue(currentPerson, kABPersonFirstNameProperty) != NULL){ 

     firstName = (__bridge_transfer NSString *)ABRecordCopyValue(currentPerson, kABPersonFirstNameProperty);   
    }  
    //If the first name property does not exist 
    else{ 
     firstName = @"NULL"; 
    } 
    return firstName;  
} 

+(NSString *)fetchJobTitleForPersonID: (NSUInteger)identifier{ 

    NSString *jobTitle; 
    ABRecordRef currentPerson = (__bridge ABRecordRef)[[PSAddressBook arrayOfContacts] objectAtIndex:identifier]; 

    if ((__bridge_transfer NSString *)ABRecordCopyValue(currentPerson, kABPersonJobTitleProperty) != NULL){ 

     jobTitle = (__bridge_transfer NSString *)ABRecordCopyValue(currentPerson, kABPersonJobTitleProperty);   
    }  
    else{ 

     jobTitle = @"NULL"; 
    } 
    return jobTitle;  
} 

arrayOfContacts是這樣定義的類方法:

+(NSArray *)arrayOfContacts{ 

    //Creates an ABAddressBookRef instance containing the data from the address book database 
    ABAddressBookRef addressBook = ABAddressBookCreate(); 

    //Creates an NSArray from the CFArrayRef using toll-free bridging 
    NSArray *arrayOfPeople = (__bridge_transfer NSArray *)ABAddressBookCopyArrayOfAllPeople(addressBook); 

    CFRelease(addressBook); 

    return arrayOfPeople; 
} 

這些方法在名爲「PSPropertyFetcher」的模型類中定義。在我的根視圖控制器中,我在viewDidLoad中放置了一些NSLog語句,以查看屬性fetcher方法是否正常工作。這裏是我的測試代碼:

NSLog(@"Property Fetchers Test\n"); 

for(NSUInteger i = 0; i <= ([PSAddressBook contactsCount]-1); i++){ 

    NSLog(@"First Name: %@", [PSPropertyFetcher fetchFirstnameForPersonID:i]); 
    NSLog(@"Middle Name: %@", [PSPropertyFetcher fetchMiddlenameForPersonID:i]); 
    NSLog(@"Last Name: %@", [PSPropertyFetcher fetchLastnameForPersonID:i]); 
    NSLog(@"Organization: %@", [PSPropertyFetcher fetchOrganizationForPersonID:i]); 
    NSLog(@"Department: %@", [PSPropertyFetcher fetchDepartmentForPersonID:i]);   
    NSLog(@"Job Title: %@\n\n", [PSPropertyFetcher fetchJobTitleForPersonID:i]);   
} 

這隻能部分;這是輸出:

2012-06-27 10:37:30.094猜猜我是誰[80103:F803]!房產取程序測試

2012-06-27 10:37:30.108猜猜我是誰[ 80103:F803]名字:時Jod

2012-06-27 10:37:30.114猜猜我是誰[80103:F803]中名:鮑勃

2012-06-27 10:37:30.118猜猜我是誰![80103:f803]姓:Satson

2012-06-27 10:37:30.122猜猜誰![80103:f803] Orga nization:強生公司

2012-06-27 10:37:30.125猜猜我是誰![80103:F803科]:NULL

2012-06-27 10:37:30.128猜猜我是誰[80103! F803]職位名稱:NULL


2012-06-27 10:37:30.136猜猜我是誰[80103:F803]名字:Shemairan

2012-06-27 10: 37:30.166猜猜誰![80103:f803]中間名:Daitran

2012-06-27 10:37:30.179猜猜我是誰![80103:F803]姓:Catairan

2012-06-27 10:37:30.184猜猜我是誰[80103:F803]!組織: Shmairo和公司

2012-06-27 10:37:30.188猜猜我是誰![80103:F803科]:NULL

2012-06-27 10:37:30.193猜猜我是誰[80103:F803 ]職位:NULL


2012-06-27 10:37:30.202猜猜我是誰![80103:F803]名字:亞歷克斯

2012-06-27 10:37:30.207猜猜我是誰[80103:F803]!中間名:約翰

2012-06-27 10:37:30。213猜猜我是誰![80103:F803]姓:玉米

2012-06-27 10:37:30.219猜猜我是誰![80103:F803]組織:蘋果

2012-06-27 10:37 :30.225猜猜我是誰![80103:F803科]:NULL

2012-06-27 10:37:30.230猜猜我是誰![80103:F803]職位名稱:NULL

在iPhone模擬器聯繫人應用程序中,我確保爲每個聯繫人填寫每個字段,但出於某種原因,「部門」和「職位」字段未正確打印。

基本上,我想知道我的「職位」和「部門」提取方法有什麼問題。

在此先感謝!

+0

我們可以看到'[self arrayOfContacts]'的實現嗎?如果它只是一個屬性,它在哪裏填充? –

+0

@JakeKing我更新了問題以顯示'arrayOfContacts' – pasawaya

回答

6

雖然看起來不太可能出現在地址簿的這麼小的範例中,但是您確實有內存泄漏,可能會讓事情失控。

假設您使用arrayOfContacts來確定[self contactsCount],那麼您將每次通過這些類方法中的每個循環泄漏2個AddressBook項。

在這個小例子中,當你啓動contactsWithJobTitleProperty時,你將只泄漏48個AddressBooks。但是,如果你從一個更大的例子中拉出了這個例子,你反覆嘗試在一個更大的AddressBook上確定這些值,那麼你可能會有數百個晃動的AddressBook對象。

添加CFRelease,如下面的代碼片段,看看是否有幫助。

+(NSArray *)arrayOfContacts{ 

    //Creates an ABAddressBookRef instance containing the data from the address book database 
    ABAddressBookRef addressBook = ABAddressBookCreate(); 

    //Creates an NSArray from the CFArrayRef using toll-free bridging 
    NSArray *arrayOfPeople = (__bridge_transfer NSArray *)ABAddressBookCopyArrayOfAllPeople(addressBook); 
    CFRelease(addressBook); 

    return arrayOfPeople; 
} 

(FWIW,將你的程序崩潰的獨立的事情是,你正在使用NSUInteger作爲循環計數器的類型,但你測試針對的是可能是值-1 ...而且由於0是NSUInteger的地板,如果你的地址簿中沒有聯繫人,這將失敗,但這不是爲什麼這個崩潰正在發生。)

+0

我會嘗試一下並回復你。 – pasawaya

+0

現在它不會崩潰,並且組織方法返回正確的值,但其他一些屬性的其他方法的某些方法不會返回正確的值。 – pasawaya

+0

什麼「組織」方法? (我想我可以假設你的意思是你有另一個類的方法,像上面那些檢索屬性kABPersonOrganizationProperty的聯繫人數量。)其他方法不返回正確的值?當您檢索它們時,並非所有類型都返回相同的類型,所以您必須確保您的__bridge或_bridge_transfer在每種情況下都有意義。 –

2

它在我看來像你可能正在訪問一個NULL值,你有沒有嘗試過,如果它是NULL之前執行橋接傳輸?

+0

我不測試它是否爲NULL值(我應該這麼感謝),但我確保爲模擬器中每個字段的每個聯繫人添加一個值。 – pasawaya

+0

沒關係。我確實檢查空值。 – pasawaya

1

這可能無法解決你的問題,但我會做一些調整,如果我是你:

+(NSUInteger)contactsWithJobTitleProperty{ 
    NSUInteger contactNumber = 0; 
    // don't call arrayOfContacts in the loop -- 
    // when you do this you are creating a new address book 
    // each time the loop executes 
    NSArray *contacts = [self arrayOfContacts]; 
    for(NSUInteger increment = 0; increment <= (contacts.count-1); increment++){ 
     ABRecordRef currentPerson = (__bridge ABRecordRef)[contacts objectAtIndex:increment]; 
     NSString *valueTest = (__bridge_transfer NSString *)ABRecordCopyValue(currentPerson, kABPersonJobTitleProperty); 

     if(valueTest != NULL) { 
      contactNumber++; 
     } 
    } 
    return contactNumber; 
} 

此外,@ john.k.doe提到,請確保我們在您的arrayOfContacts方法中使用e CFRelease(addressBook);

+0

謝謝!我改變了我的代碼,現在我在for循環之前創建了一個類似'NSArray * contacts = [PSAddressBook arrayOfContacts]'的地址簿。我還將'CFRelease(addressBook)'行添加到'arrayOfContacts'。 – pasawaya

0

剛遇到同樣的問題。參見Jokinryou Tsui的answer here

基本上,如果您有可用聯繫人的不同來源的情況,並且它們並非都是本地(默認設置),那麼最終的結果可能是您要拖動的聯繫人數量不匹配,嘗試訪問不存在的索引處的ABRecordRef。 ABRecordRef將有一個值(所以NULL檢查本身不會這樣做),但該值將是垃圾,並且在嘗試複製其任何值時,您將獲得BAD ACCESS。

希望這會有所幫助。