我正在尝试从 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
会导致崩溃。
self.allContacts
是所有联系人的数组self.allKeys
是所有属性的数组(每个属性都是字符串)当尝试从 ABRecordCopyValue
检索单个属性时,会导致 EXC_BAD_ACCESS
崩溃。
谢谢!
设置 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 Reference和 CFTypeRef 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 |