2011-10-12 2 views
2

iPhone 주소록에서 데이터를 가져 오려고하는데 문제가 있습니다.ABRecordCopyValue 및 ABPropertyID 충돌이 발생했습니다.


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

나는 또한 모든 속성의 배열 (문자열로 각 속성)가이 self.allKeys라고 : 모든

첫째, 나는 모든 연락처의 배열 (self.allContacts)가 있습니다.


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

문제는 ABRecordCopyValuecurrentFieldProperty을 전달하는 것은 충돌이 발생한다는 것입니다 : 나는 self.allKeys에서 속성을 사용하여 속성을 가져올하려고 할 때

충돌

가 발생합니다.
  • self.allContacts

  • self.allKeys 모든 속성들의 배열 (문자열 등의 각 특성)

ABRecordCopyValue에서 하나의 속성을 검색하는 그것이 원인 모든 콘택트의 배열 인 EXC_BAD_ACCESS 충돌.

감사합니다.

+0

self.allKeys가 채워지는 방법을 언급하지 않았습니다. 또한, 충돌시 얻을 수있는 유용한 정보가 있습니까? – Stavash

+0

self.allKeys는 kABPersonFirstNameProperty와 같은 모든 ABPropertyID 속성을 보유하는 배열입니다. 충돌시 로그를 수신하지 않습니다. –

+0

ABRecordCopyValue가 충돌을 일으킨다는 것을 어떻게 알 수 있습니까? EXC_BAD_ACCESS를 받으십니까? SIGBRT? 그 문제에 대해 어떤 생각을 밝힐만한 것이 있습니까? – Stavash

답변

4

디버거에서 NSZombieEnabled, MallocStackLoggingguard malloc을 설정하십시오.

(gdb) info malloc-history 0x543216 

가 충돌의 원인이 된 객체의 주소 0x543216 교체, 당신은 훨씬 더 유용한 스택 추적을 얻을 것이다 그것을 당신이 정확하게 도움이 될 것입니다 그런 다음 응용 프로그램이 충돌 할 때, gdb를 콘솔에서이 입력 문제를 일으키는 코드의 정확한 줄


 

- 더 생각 -

self.allKeys 실제로

이 "모든 속성의 배열 (문자열로 각 속성)"다음

당신은 아마 가야 ABPropertyID은이므로 배열 객체 (속성)의 . 같은 뭔가 :

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

그러나 우리는 self.allKeys의 값을 참조하거나이 확실하게 채워집니다 어떻게해야합니다.

ABRecordCopyValue

ABRecordRef Reference에서

CFTypeRef Reference-는 기록 프로퍼티의 값을 돌려줍니다.

CFTypeRef ABRecordCopyValue (
     ABRecordRef record, 
     ABPropertyID property 
    ); 

매개 변수
record-문제의 속성을 포함하는 기록.
property - 값이 반환되는 레코드의 속성입니다. 레코드 재산의

반환 값
값.

그리고 :

ABPropertyID - 기록 속성을 식별 정수.
typedef int32_t ABPropertyID;


  - 그리고 자세한 문제 해결 아이디어 - 당신이 (NSString*)ABRecordCopyValue(currentRecordRef, currentFieldProperty)NSString *CFTypeRef 캐스팅 할 때

(가) 위의 경우가 아닌 경우는, 다음 충돌은 그래서 여기입니다 발생할 수 있습니다 그걸 해결할 수있는 작은 도우미 기능 :

- (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 먼저 순서가 무엇인지 확인하십시오.)

(210)
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; 
} 

그런 다음 배열 [self.allKeys objectAtIndex:j]에서 stringToABPropertyID: 값을 전달하고 반환 할 것 ABPropertyID :

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

자세한 답변을 주셔서 대단히 감사합니다. 어떤 이유로 (ABPropertyID) [[self.allKeys objectAtIndex : j] intValue]; as (null) –

+0

@GuyDor'[self.allKeys objectAtIndex : j]'에 빈 문자열이있을 수 있습니다. 'NSLog (@ "% @", [self.allKeys objectAtIndex : j]);를 실행하고 출력 내용을 확인하십시오. – chown

+0

빈 문자열이 아님 ... –

0

내가 답변으로 내 이전 코멘트를 게시하도록하겠습니다 :

내가 특히 생각을 줄 것이다 currentFieldProperty의 값으로 - 사전에서 추출 되었기 때문에 객체이지만 열거 형 값을받는 것으로 가정합니다. 어쩌면

currentFieldProperty = (ABPropertyID)[[self.allKeys objectAtIndex:j] intValue]; 
0

몇 가지 문제를보십시오 :

  • ABPropertyID 개체 유형이 아닙니다. (ABPropertyID)[self.allKeys objectAtIndex:j]은 분명히 잘못되었습니다."모든 속성 (문자열로 각 속성)의 배열"이 될 수도 있습니다. 무슨 끈이야? 이 문자열은 어디에서 가져 왔습니까? 예를 들어 부동산 이름의 문자열에 대해 이야기하고 있다면 @"kABPersonEmailProperty" 그런 다음 그 값을 얻는 것은 거의 불가능합니다.
  • kABPersonEmailProperty과 같은 ABPropertyID 값은 상수가 아닙니다. 변수이며 처음 주소록을 초기화 한 후에 만 ​​초기화 된 것처럼 보입니다.
관련 문제