OStack程序员社区-中国程序员成长平台

标题: iphone - ABRecordCopyValue 和 ABPropertyID 崩溃 [打印本页]

作者: 菜鸟教程小白    时间: 2022-12-12 17:42
标题: iphone - ABRecordCopyValue 和 ABPropertyID 崩溃

我正在尝试从 iPhone 通讯录中检索数据,但遇到了一些问题。

首先,我有一个包含所有联系人的数组(self.allContacts):


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

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

当我尝试使用 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 会导致崩溃。


当尝试从 ABRecordCopyValue 检索单个属性时,会导致 EXC_BAD_ACCESS 崩溃。

谢谢!



Best Answer-推荐答案


设置 NSZombieEnabled , MallocStackLogging , 和 guard malloc在调试器中。然后,当您的应用程序崩溃时,在 gdb 控制台中输入以下内容:

(gdb) info malloc-history 0x543216

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


- 更多想法 -

如果 self.allKeys 确实是

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

那么您可能应该得到数组对象(属性)的 intValue,因为 ABPropertyID 只是一个 typedef int32_t。比如:

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

但我们需要查看 self.allKeys 中的值或它的填充方式才能确定。

来自 ABRecordRef ReferenceCFTypeRef Reference

ABRecordCopyValue - Returns the value of a record property.

    CFTypeRef ABRecordCopyValue (
       ABRecordRef record,
       ABPropertyID property
    );

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

Return Value
The value of property in record.

还有:

ABPropertyID - Integer that identifies a record property.
typedef int32_t ABPropertyID;


- 以及更多故障排除想法 -

如果不是上述情况,那么当你在 (NSString*)ABRecordCopyValue(currentRecordRef, currentFieldProperty) 所以这里有一个小辅助函数可以解决这个问题:

- (NSString*)stringValueForCFTypeCFTypeRef)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 处有一个对象:

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]);
}

编辑(关于评论):

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

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

- (NSString *)ABPropertyIDToStringABPropertyID)propertyVal {
    return ABPropertyID_toString[propertyVal];
}

- (ABPropertyID)stringToABPropertyIDNSString *)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:

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

关于iphone - ABRecordCopyValue 和 ABPropertyID 崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7746111/






欢迎光临 OStack程序员社区-中国程序员成长平台 (https://ostack.cn/) Powered by Discuz! X3.4