【问题标题】:How do you get a persons phone number from the address book?你如何从通讯录中得到一个人的电话号码?
【发布时间】:2009-07-13 03:14:44
【问题描述】:

我想做的就是让用户从通讯录中选择一个号码。我在这个问题中找到了代码:

How to get a Phone Number from an Address Book Contact (iphone sdk)

ABMultiValueRef container = ABRecordCopyValue(person, property);
CFStringRef contactData = ABMultiValueCopyValueAtIndex(container, identifier);
CFRelease(container);
NSString *contactString = [NSString stringWithString:(NSString *)contactData];
CFRelease(contactData);

问题是在第二行(在 3.0 设备上运行时)我收到以下错误:

帐户管理器找不到标识符为 MobileMe:rustyshelf 的帐户

接着是:

节目接收信号:“EXC_BAD_ACCESS”。

这一切都在选择器委托方法中:

- (BOOL)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker shouldContinueAfterSelectingPerson:(ABRecordRef)person property:(ABPropertyID)property identifier:(ABMultiValueIdentifier)identifier{

这只是我通讯录中的一个联系人,与 Mobile Me 同步

编辑:我认为这可能是 SDK 的一个错误,它发生在我的一些联系人身上,但没有发生在其他联系人身上......

【问题讨论】:

    标签: iphone


    【解决方案1】:

    “标识符”参数不包含所触及记录的 CFIndex。我用来告诉用户选择哪个电话号码的方法是这样的:

    - (BOOL)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker shouldContinueAfterSelectingPerson:(ABRecordRef)person property:(ABPropertyID)property identifier:(ABMultiValueIdentifier)identifier
    {
        if (property == kABPersonPhoneProperty) {
            ABMultiValueRef multiPhones = ABRecordCopyValue(person, kABPersonPhoneProperty);
            for(CFIndex i = 0; i < ABMultiValueGetCount(multiPhones); i++) {
                if(identifier == ABMultiValueGetIdentifierAtIndex (multiPhones, i)) {
                    CFStringRef phoneNumberRef = ABMultiValueCopyValueAtIndex(multiPhones, i);
                    CFRelease(multiPhones);
                    NSString *phoneNumber = (NSString *) phoneNumberRef;
                    CFRelease(phoneNumberRef);
                    txtPhoneNumber.text = [NSString stringWithFormat:@"%@", phoneNumber];
                    [phoneNumber release];
                }
            }
        }
    
        [self dismissModalViewControllerAnimated:YES];
        return NO;
    }
    

    【讨论】:

    • 注意过度发布 - 如果此人有多个电话号码,则可能会意外发布“多个 iPhone”。还有“phoneNumber”和“phoneNumberRef”。
    • 是的,您应该编辑您的帖子。这是一个更好的 for 循环: for(CFIndex i = 0; i
    • 为什么要在 for 循环中发布 multiphones?
    【解决方案2】:

    离开 JWD 的答案,这是一个更安全的版本,它使用内置常量并选择 iphone 号码而不是另一个手机号码...

    ABMultiValueRef phones =(NSString*)ABRecordCopyValue(person, kABPersonPhoneProperty);
    NSString* mobile=@"";
    NSString* mobileLabel;
    for(CFIndex i = 0; i < ABMultiValueGetCount(phones); i++) {
        mobileLabel = (NSString*)ABMultiValueCopyLabelAtIndex(phones, i);
        if([mobileLabel isEqualToString:(NSString *)kABPersonPhoneMobileLabel])
        {
            [mobile release] ;
            mobile = (NSString*)ABMultiValueCopyValueAtIndex(phones, i);
        }
        else if ([mobileLabel isEqualToString:(NSString*)kABPersonPhoneIPhoneLabel])
        {
            [mobile release] ;
            mobile = (NSString*)ABMultiValueCopyValueAtIndex(phones, i);
            break ;
        }
    }
    

    【讨论】:

      【解决方案3】:
      - (BOOL)personViewController:(ABPersonViewController *)personViewController shouldPerformDefaultActionForPerson:(ABRecordRef)person property:(ABPropertyID)property identifier:(ABMultiValueIdentifier)identifierForValue
      {
         if (property == kABPersonPhoneProperty)
         {
             ABMultiValueRef numbers = ABRecordCopyValue(person, property);
             NSString* targetNumber = (__bridge NSString *) ABMultiValueCopyValueAtIndex(numbers, ABMultiValueGetIndexForIdentifier(numbers, identifierForValue));
      
             NSLog(@"%@", targetNumber);
         }
         return NO;
      }
      

      我使用这个问题来构建自己的解决方案。我发布的代码不是为了回答,只是为了有人可能会觉得有用。这些是获取房产的简单步骤。不包括内存管理。

      【讨论】:

      • +1 嘿,这行得通!我的问题是当我选择标有“Mobile”,“家”或“工作”的电话号码时,我的应用程序很好,但选择“iPhone”时,我的应用程序崩溃了。你的回答拯救了我的一天。谢谢。
      • 此代码泄漏内存。首先numbers 永远不会被释放,你应该在使用完之后调用CFRelease(numbers)。其次,targetNumber 永远不会被释放。你应该使用__bridge_transfer 而不是简单的__bridge 来解决这个问题。
      【解决方案4】:

      我使用它从 ABRecordRef/ 中提取手机号码“记录”变量是您想要的电话号码的 ABRecordRef。在我有“”的地方,您可以使用另一个电话标签字符串来查找其他类型的电话号码。

      //Get mobile phone number
      ABMultiValueRef phones =(NSString*)ABRecordCopyValue(record, kABPersonPhoneProperty);
      NSString* mobile=@"";
      NSString* mobileLabel;
      for(CFIndex i = 0; i < ABMultiValueGetCount(phones); i++) {
          mobileLabel = (NSString*)ABMultiValueCopyLabelAtIndex(phones, i);
          if([mobileLabel isEqualToString:@"_$!<Mobile>!$_"]) {
                mobile = (NSString*)ABMultiValueCopyValueAtIndex(phones, i);
          }
      }
      

      【讨论】:

      • 该代码不会找不到带有“iPhone”标签的手机号码。至少在澳大利亚,对于通过彩信收到的联系人来说,这似乎是自动发生的。
      • 你说得对,我发布的代码只是搜索标记为“$!!$”的数字。它还在 for 循环中循环所有结果,因此您可以轻松地将“$!!$”更改为“iPhone”,它应该可以工作。
      【解决方案5】:

      您应该能够执行以下操作:

      ABMultiValueRef phoneNumbers = (ABMultiValueRef)ABRecordCopyValue(person, kABPersonPhoneProperty);
      CFRelease(phoneNumbers);
      NSString* phoneNumber = (NSString*)ABMultiValueCopyValueAtIndex(phoneNumbers, 0);
      

      当然,这只会让您获得与被选中的人相关联的第一批(可能)许多人。

      【讨论】:

      • 感谢您的回答,但我只想找到用户点击的号码。我认为我的代码是正确的,但听起来固件 3.0 中有一个错误阻止我获取它。上面的代码适用于我的一些联系人,但不适用于其他人。
      • @Nathan:如果联系人没有电话号码怎么办?
      【解决方案6】:

      您也可以像在此代码中一样使用此“ABMultiValueGetIndexForIdentifier”:

      ABPropertyType pt = ABPersonGetTypeOfProperty(property);
      NSString *phoneNumber;
      if ((pt & kABMultiValueMask) == kABMultiValueMask) {
              ABMultiValueRef phoneProperty = ABRecordCopyValue(person,property);
              CFIndex idx = ABMultiValueGetIndexForIdentifier(phoneProperty, identifier);
              phoneNumber = (NSString *)ABMultiValueCopyValueAtIndex(phoneProperty,idx);
              CFRelease(phoneProperty);
          } 
      

      【讨论】:

        【解决方案7】:

        从丹的回答出发:

        - (BOOL)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker shouldContinueAfterSelectingPerson:(ABRecordRef)person 
                                        property:(ABPropertyID)property 
                                      identifier:(ABMultiValueIdentifier)identifier
        {
            if (property == kABPersonPhoneProperty) { // if tapped is equal to a phone property
                CFStringRef cfnumber;
                ABMultiValueRef numbers = ABRecordCopyValue(person, kABPersonPhoneProperty); 
                for(CFIndex i = 0; i < ABMultiValueGetCount(numbers); i++) {
                    if(identifier == ABMultiValueGetIdentifierAtIndex (numbers, i)) { //if tapped number identifier is the same as identifier number tapped
                        cfnumber = ABMultiValueCopyValueAtIndex(numbers, i); // copy the number to CFSTRING number
                    }
                }        
                NSString *number = [NSString stringWithFormat:@"%@",cfnumber];
                CFRelease(cfnumber); 
                //do anything you want with the number
            }
            return NO;
        }
        

        无法告诉您这是否是最好/正确的方法。但是我在使用 Dan 的代码时遇到了一些错误。因此我决定在弄清楚之后分享它。 还在学习目标c..哈哈.. 希望对你有帮助。。

        问候, 史蒂夫0hh

        【讨论】:

          猜你喜欢
          • 2012-10-27
          • 1970-01-01
          • 2012-12-10
          • 2010-12-30
          • 1970-01-01
          • 2023-03-22
          • 2013-11-14
          • 1970-01-01
          • 2011-07-19
          相关资源
          最近更新 更多