ABRecordCopyValue和ABPropertyID崩溃 [英] ABRecordCopyValue and ABPropertyID crash

查看:104
本文介绍了ABRecordCopyValue和ABPropertyID崩溃的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试从iPhone地址簿中检索数据,但我遇到了一些问题。

I'm trying to retrieve data from the iPhone address book and I have some problems.

首先,我有一系列所有联系人( self.allContacts ):

First of all, I have an array of all contacts (self.allContacts):


ABAddressBookRef abRef = ABAddressBookCreate();     
self.allContacts = (NSMutableArray*)ABAddressBookCopyArrayOfAllPeople(abRef);

我还有一个名为的所有属性的数组(每个属性都是字符串) self.allKeys

当我尝试使用 self.allKeys <中的属性获取属性时发生崩溃/ code>:

The crash occurs when I try to get the properties using a property from self.allKeys:


NSString *currentRecord = [[NSString alloc] init];
ABRecordRef currentRecordRef;
ABPropertyID currentFieldProperty;

currentRecordRef =  (ABRecordRef)[self.allContacts objectAtIndex:i];
currentFieldProperty = (ABPropertyID)[self.allKeys objectAtIndex:j];

currentRecord = (NSString*)ABRecordCopyValue(currentRecordRef, currentFieldProperty);                                   

问题是将 currentFieldProperty 传递给 ABRecordCopyValue 导致崩溃。

The problem is that passing currentFieldProperty to ABRecordCopyValue causes a crash.


  • self.allContacts 是所有联系人的数组

  • self.allKeys 是所有属性的数组(每个属性为字符串)

  • self.allContacts is an array of all contacts
  • self.allKeys is an array of all properties (each property as string)

尝试从 ABRecordCopyValue <检索单个属性时/ code>它导致 EXC_BAD_ACCESS 崩溃。

谢谢!

推荐答案

设置 NSZombieEnabled MallocStackLogging guard malloc 。然后,当您的应用程序崩溃时,在gdb控制台中键入:

Set NSZombieEnabled, MallocStackLogging, and guard malloc in the debugger. Then, when your App crashes, type this in the gdb console:

(gdb) info malloc-history 0x543216

将0x543216替换为导致崩溃的对象的地址,您将获得更有用的堆栈跟踪应该可以帮助您查明导致问题的代码中的确切行。

Replace 0x543216 with the address of the object that caused the crash, and you will get a much more useful stack trace and it should help you pinpoint the exact line in your code that is causing the problem.

  - 更多想法 -

 - More thoughts -

如果 self.allKeys 确实是


所有属性的数组(每个属性为字符串)

"an array of all properties (each property as string)"

那么你应该得到 intValue 数组对象(属性),因为 ABPropertyID 只是 typedef int32_t 。类似于:

then you should probably get the intValue of the array object (property) since an ABPropertyID is just a typedef int32_t. Something like:

currentFieldProperty = (ABPropertyID)[[self.allKeys objectAtIndex:j] intValue];
ABRecordCopyValue(currentRecordRef, currentFieldProperty)

但我们需要查看<$中的值c $ c> self.allKeys 或如何填充以确保。

But we would need to see the values in self.allKeys or how it is populated to be sure.

来自 ABRecordRef参考 CFTypeRef参考


ABRecordCopyValue - 返回记录属性的值。

    CFTypeRef ABRecordCopyValue (
       ABRecordRef record,
       ABPropertyID property
    );

参数

记录 - 包含相关财产的记录。

property - 正在退还其价值的记录的属性。

Parameters
record - The record containing the property in question.
property - The property of record whose value is being returned.

返回值

记录中的财产价值。

并且:


ABPropertyID - 标识记录属性的整数。

typedef int32_t ABPropertyID;






  - 以及更多疑难解答提示 -


 - And more troubleshooting ideas -

如果上述情况不是这样,那么当您投出 CFTypeRef NSString * (NSString *)ABRecordCopyValue(currentRecordRef,currentFieldProperty)所以这里有一个小帮手可以解决这个问题的函数:

If the above is not the case, then your crash may be caused when you cast CFTypeRef to NSString * in (NSString*)ABRecordCopyValue(currentRecordRef, currentFieldProperty) so here is a little helper function that might solve that:

- (NSString*)stringValueForCFType:(CFTypeRef)cfValue {
    NSString *stringValue = nil;
    if (!cfValue) return nil;
    CFTypeID cfType = CFGetTypeID(cfValue);
    if (cfType == CFStringGetTypeID()) {
        stringValue = [[(id)CFMakeCollectable(cfValue) retain] autorelease];
    } else if (cfType == CFURLGetTypeID()) {
        stringValue = [(NSURL*)cfValue absoluteString];
    } else if (cfType == CFNumberGetTypeID()) {
        stringValue = [(NSNumber*)cfValue stringValue];
    } else if (cfType == CFNullGetTypeID()) {
        stringValue = [NSString string];
    } else if (cfType == AXUIElementGetTypeID()) {
        stringValue = [[GTMAXUIElement elementWithElement:cfValue] description];
    } else if (cfType == AXValueGetTypeID()) {
        stringValue = [self stringValueForAXValue:cfValue];
    } else if (cfType == CFArrayGetTypeID()) {
        stringValue = [self stringValueForCFArray:cfValue];
    } else if (cfType == CFBooleanGetTypeID()) {
        stringValue = CFBooleanGetValue(cfValue) ? @"YES" : @"NO";
    } else {
        CFStringRef description = CFCopyDescription(cfValue);
        stringValue = [(id)CFMakeCollectable(description) autorelease];
  }
  return stringValue;       
}

然后执行 currentRecord = [self stringValueForCFType:ABRecordCopyValue( currentRecordRef,currentFieldProperty)]; 并检查以确保 self.allKeys 在索引 j self.allContacts 在索引 i 中有一个对象:

Then do currentRecord = [self stringValueForCFType:ABRecordCopyValue(currentRecordRef, currentFieldProperty)]; and check to make sure self.allKeys has an object at index j and self.allContacts has an object at index i:

NSString *currentRecord = [[NSString alloc] init];
ABRecordRef currentRecordRef;
ABPropertyID currentFieldProperty;

if (self.allContacts.count > i) {
    currentRecordRef = (ABRecordRef)[self.allContacts objectAtIndex:i];    
    if (self.allKeys.count > j) {
        currentFieldProperty = (ABPropertyID)[self.allKeys objectAtIndex:j];
        currentRecord = [self stringValueForCFType:ABRecordCopyValue(currentRecordRef, currentFieldProperty)];
    } else {
        NSLog(@"self.allKeys has no value at index (%d): %@", j, [allKeys description]);
    }
} else {
    NSLog(@"self.allContacts has no value at index (%d): %@", i, [allContacts description]);
}






编辑(关于评论):


Edit (regarding the comments):

要将属性名称的字符串转换为其int值,您需要创建以下内容(这可能不是他们需要的正确顺序,所以 NSLog 他们首先看看他们需要的订单):

To convert string of property name to its int value, you need to create the following (this probably is not be the correct order that they need to be in, so NSLog them first to see what order they need to be in):

NSString * const ABPropertyID_toString[] = {
    @"kABPersonFirstNameProperty",
    @"kABPersonLastNameProperty",
    @"kABPersonMiddleNameProperty",
    @"kABPersonPrefixProperty",
    @"kABPersonSuffixProperty",        
    @"kABPersonNicknameProperty", 
    @"kABPersonFirstNamePhoneticProperty",
    @"kABPersonLastNamePhoneticProperty", 
    @"kABPersonMiddleNamePhoneticProperty", 
    @"kABPersonOrganizationProperty", 
    @"kABPersonJobTitleProperty", 
    @"kABPersonDepartmentProperty", 
    @"kABPersonEmailProperty", 
    @"kABPersonBirthdayProperty", 
    @"kABPersonNoteProperty", 
    @"kABPersonCreationDateProperty", 
    @"kABPersonModificationDateProperty", 
    @"kABPersonAddressProperty", 
    // ... etc
};

- (NSString *)ABPropertyIDToString:(ABPropertyID)propertyVal {
    return ABPropertyID_toString[propertyVal];
}

- (ABPropertyID)stringToABPropertyID:(NSString *)propertyString {
    int retVal;
    for(int i=0; i < sizeof(ABPropertyID_toString) - 1; ++i) {
        if([(NSString *)ABPropertyID_toString[i] isEqual:propertyString]) {
            retVal = i;
            break;
        }
    }
    return retVal;
}

然后传递 stringToABPropertyID:数组 [self.allKeys objectAtIndex:j] 中的值,您将返回 ABPropertyID

Then pass stringToABPropertyID: the value from the array [self.allKeys objectAtIndex:j] and you will be returned an ABPropertyID:

currentFieldProperty = [self stringToABPropertyID:[self.allKeys objectAtIndex:j]];

这篇关于ABRecordCopyValue和ABPropertyID崩溃的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆