Установить NSZombieEnabled , MallocStackLogging и guard malloc в отладчике.Затем, когда произойдет сбой вашего приложения, введите его в консоли gdb:
(gdb) info malloc-history 0x543216
Замените 0x543216 на адрес объекта, вызвавшего сбой, и вы получите гораздо более полезную трассировку стека, и это должно помочьВы указываете точную строку в своем коде, которая вызывает проблему.
- Дополнительные мысли -
Если self.allKeys
действительно
"массив всех свойств (каждое свойство в виде строки) "
, тогда вы, вероятно, должны получить intValue
объекта массива (свойства), поскольку ABPropertyID
- это просто typedef int32_t
.Что-то вроде:
currentFieldProperty = (ABPropertyID)[[self.allKeys objectAtIndex:j] intValue];
ABRecordCopyValue(currentRecordRef, currentFieldProperty)
Но нам нужно увидеть значения в self.allKeys
или как оно заполнено, чтобы быть уверенным.
Из Ссылка ABRecordRef и CFTypeRef Reference
ABRecordCopyValue
- Возвращает значение свойства записи.
CFTypeRef ABRecordCopyValue (
ABRecordRef record,
ABPropertyID property
);
Параметры record
- Запись, содержащая данное свойство. property
- Свойство записи, значение которой возвращается.
Возвращаемое значение Значение свойства в записи.
И:
ABPropertyID
- Целое число, идентифицирующее свойство записи. typedef int32_t ABPropertyID;
- и другие идеи по устранению неполадок -
Если вышеприведенное не так, то ваш сбой может быть вызван тем, что вы произвели CFTypeRef
на NSString *
в (NSString*)ABRecordCopyValue(currentRecordRef, currentFieldProperty)
, так вот небольшая вспомогательная функция, которая может решить эту проблему:
- (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
:
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 *)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
:
currentFieldProperty = [self stringToABPropertyID:[self.allKeys objectAtIndex:j]];