ios - ABRecordCopyValue() EXC_BAD_ACCESS Error while getting kABPersonFirstNameProperty

标签 ios iphone objective-c ios7 abaddressbook

我正在将我一年前为 iOS 6 编写的应用程序升级到 iOS 7/8,我收到了这个 EXC_BAD_ACCESS 错误,这在我的旧版本中从未发生过。

在我的应用程序中,我试图获取某些联系信息,例如名字、姓氏、电话号码、照片。申请流程如下:

1) 点击一个按钮,出现地址簿。

2) 选择任何联系人。

3.1) 如果联系人只有一个电话号码,更新标签。

3.2) 如果联系人有多个电话号码,请在操作表中表示它们,无论用户选择什么号码,都会将该号码更新到 UILabel。

现在,如果一个联系人只有一个电话号码,应用程序可以正常工作而不会崩溃。即 1-->2-->3.1 路径。但是,如果一个联系人有多个电话,并且一旦从操作表中选择了一个联系人号码,它就会在此行崩溃。

 CFTypeRef firstNameCF = (__bridge CFTypeRef)(CFBridgingRelease(ABRecordCopyValue(sharedSingleton.personGlobal, kABPersonFirstNameProperty)));

详细代码


1) 选择联系人

- (BOOL)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker
  shouldContinueAfterSelectingPerson:(ABRecordRef)person {

  sharedSingleton.personGlobal = nil;
  sharedSingleton.personGlobal=person; // ====> Save a ABRecordRef object globally. 
   //^^^ Could this be a culprit? I tried to make it private variable also at first.

  [self displayAndVerifyPerson]; // No 2 below.
  [self dismissViewControllerAnimated:YES completion:^{
   }];
  return NO;
}

2) 将检查有多少电话号码的人。 0/1/>1.

  If 0 show no phone no error. 

  If 1 phone update label by calling updateLabel.

  If >1 represent action sheet for user to select number. And on clickedButtonIndex call updateLabel.

-(void)displayAndVerifyPerson
{
 ABMultiValueRef phoneNumbers = ABRecordCopyValue(sharedSingleton.personGlobal,kABPersonPhoneProperty); //ABRecordRef which globally saved.
 globalContact=nil;  //NSString to store selected number. Works fine.
//self.personGlobal=person;
 NSArray *phoneNumberArray = (__bridge_transfer NSArray *)ABMultiValueCopyArrayOfAllValues(phoneNumbers);
 CFRelease(phoneNumbers);

 if (ABMultiValueGetCount(phoneNumbers) > 0){ //Check if a contact has any number

    NSLog(@" Number--> %@",phoneNumberArray); //Prints numbers correct whether no of contacts are 0/1/>1.

    if ([phoneNumberArray count]==1){  //If exactly one contact number no problem.
        globalContact = [phoneNumberArray objectAtIndex:0];
        NSLog(@"--> %@",globalContact);
        [self updateLabel];  // No 3 Below.
    }
    // We have multiple numbers so select any one.
    else{
        UIActionSheet *actionSheet = [[UIActionSheet alloc] initWithTitle:@"Select Number"
                                                                 delegate:self
                                                        cancelButtonTitle:nil
                                                   destructiveButtonTitle:nil
                                                        otherButtonTitles:nil];
        actionSheet.delegate=self;
        actionSheet.tag=0;
        for(int i=0;i<[phoneNumberArray count];i++){
            [actionSheet addButtonWithTitle:[phoneNumberArray objectAtIndex:i]];
        }
        [actionSheet addButtonWithTitle:@"Cancel"];
        actionSheet.destructiveButtonIndex = actionSheet.numberOfButtons - 1;
        actionSheet.actionSheetStyle = UIActionSheetStyleBlackTranslucent;

        UIWindow* window = [[[UIApplication sharedApplication] delegate] window];

        if ([window.subviews containsObject:self.view])
            [actionSheet showInView:self.view];
        else 
            [actionSheet showInView:window];
    }
 }
 else{ //No contact found. Display alert.

    UIAlertView *av = [[UIAlertView alloc] initWithTitle:@"Error"
                                                 message:@"No contact numebr found."
                                                delegate:self
                                       cancelButtonTitle:@"OK"
                                       otherButtonTitles:nil];
    [av show];
    return;
  }
}

3) 从 ABRecordRef 对象中获取名字、姓氏和图像。

-(void)updateLabel{

// ----------------- Get First Name From Global ABRecordRef personGlobal---------------------

    CFTypeRef firstNameCF = (__bridge CFTypeRef)(CFBridgingRelease(ABRecordCopyValue(sharedSingleton.personGlobal, kABPersonFirstNameProperty)));
    ^^^^^^^^^^^^^^^^^^^^^^
    Crashes only when `updateLabel` called from Actionsheet delegate `clickedButtonAtIndex`   

    NSString *fName = (NSString *)CFBridgingRelease(firstNameCF);
    if ([fName length]==0){
        UIAlertView *av = [[UIAlertView alloc] initWithTitle:@"Error"
                                                 message:@"Contact name not found."
                                                delegate:self
                                       cancelButtonTitle:@"OK"
                                       otherButtonTitles:nil];
        [av show];
        return;
    }
    self.lblFirstName.text = fName; //Set label with first Name.
    self.lblHomePhone.text = self.globalContact;//Set number label.
}

4) 操作表委托(delegate)

-(void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex {

  NSString *buttonTitle=[actionSheet buttonTitleAtIndex:buttonIndex];
  if(actionSheet.tag==0){
     //Printing multiple phone numbers which works and prints perfect.
     NSLog(@"Lets see what you got: ===> %@",buttonTitle); 

     if([buttonTitle isEqualToString:@"Cancel"])
        return;

     globalContact=buttonTitle;  // Save contact to NSString for later use.
     [self updateLabel];  // No. 3.
  }
}

额外说明:

1) 我寻找解决方案的问题(只有 3 个)。

我)ABRecordCopyValue() EXC_BAD_ACCESS Error

ii) EXC_BAD_ACCESS when adding contacts from Addressbook?

iii) kABPersonFirstNameProperty… trowing EXC_BAD_ACCESS

2) Sample project on dropbox if someone is generous/curious enough and wants to run and check.

3)我对这个错误的怀疑:

  • 相同的代码适用于 App Store 上的当前应用程序(为 iOS 6 编写),但在 iOS 7 上崩溃。

  • 可能是由于 Core Foundation 的内存管理。我试图在我使用的任何地方释放 Core Foundation 对象,因为 ARC 不会处理它们。但如果是这种情况,那么当联系人只有一个电话号码时它也应该崩溃。

  • 线程问题?由于应用程序只崩溃了 shen 联系人有多个电话号码,我相信操作表委托(delegate)方法 clickedButtonAtIndex 在后台线程上运行并且出现问题? (只是随机猜测!)

    我已尽力使我的问题简单易懂且内容丰富。任何建议、评论或解决方案都将不胜感激,因为过去 3 天我一直在努力解决这个问题。谢谢!

最佳答案

你处理 CoreFoundation:

sharedSingleton.personGlobal=person;

=>

因为它不是弧形对象,所以你必须保留它

CFRetain(person);
sharedSingleton.personGlobal=person; 

完成后释放

- dealloc {
    CFRelease(sharedSingleton.personGlobal);    
}

关于ios - ABRecordCopyValue() EXC_BAD_ACCESS Error while getting kABPersonFirstNameProperty,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24320386/

相关文章:

iphone - 如何在 iOS 设备上模拟磁盘空间不足的情况?

ios - 返回 block 的方法

iphone - 取消引用空指针,但我没有使用指针

IOS- swift : OrPredicate in CloudKit results in invalid

ios - StoreKit 仅崩溃 ios 10

iphone - 在ScrollView中查找TextField相对于屏幕的坐标

iphone - 将 OpenGL 1.1 代码转换为 OpenGL 2.0

objective-c - NSTask 和 NSPipe 示例与命令行 objective-c 通信

android - Urban Airship + MeteorJS 集成

ios - 在 UITableView 上激活 Speech to Text