iphone - ABRecordCopyValue 和 ABPropertyID 崩溃
<p><p>我正在尝试从 iPhone 通讯录中检索数据,但遇到了一些问题。</p>
<p>首先,我有一个包含所有联系人的数组(<code>self.allContacts</code>):</p>
<pre><code>
ABAddressBookRef abRef = ABAddressBookCreate();
self.allContacts = (NSMutableArray*)ABAddressBookCopyArrayOfAllPeople(abRef);
</code></pre>
<p>我还有一个名为 <code>self.allKeys</code> 的所有属性(每个属性都为字符串)的数组。</p>
<p>当我尝试使用 <code>self.allKeys</code> 中的属性获取属性时发生崩溃:</p>
<pre><code>
NSString *currentRecord = [ init];
ABRecordRef currentRecordRef;
ABPropertyID currentFieldProperty;
currentRecordRef =(ABRecordRef);
currentFieldProperty = (ABPropertyID);
currentRecord = (NSString*)ABRecordCopyValue(currentRecordRef, currentFieldProperty);
</code></pre>
<p>问题在于将 <code>currentFieldProperty</code> 传递给 <code>ABRecordCopyValue</code> 会导致崩溃。</p>
<hr/>
<ul>
<li><code>self.allContacts</code> 是所有联系人的数组</li>
<li><code>self.allKeys</code> 是所有属性的数组(每个属性都是字符串)</li>
</ul>
<p>当尝试从 <code>ABRecordCopyValue</code> 检索单个属性时,会导致 <code>EXC_BAD_ACCESS</code> 崩溃。</p>
<p>谢谢!</p></p>
<br><hr><h1><strong>Best Answer-推荐答案</ strong></h1><br>
<p><p>设置 <a href="http://www.cocoadev.com/index.pl?NSZombieEnabled" rel="noreferrer noopener nofollow">NSZombieEnabled</a> , <a href="http://www.cocoadev.com/index.pl?MallocStackLogging" rel="noreferrer noopener nofollow">MallocStackLogging</a> , 和 <a href="http://developer.apple.com/library/ios/ipad/#DOCUMENTATION/Performance/Conceptual/ManagingMemory/Articles/MallocDebug.html" rel="noreferrer noopener nofollow">guard malloc</a>在调试器中。然后,当您的应用程序崩溃时,在 gdb 控制台中输入以下内容:</p>
<pre><code>(gdb) info malloc-history 0x543216
</code></pre>
<p>将 0x543216 替换为导致崩溃的对象的地址,您将获得更有用的堆栈跟踪,它应该可以帮助您查明代码中导致问题的确切行。</p>
<hr/>
<p> - 更多想法 -</p>
<p>如果 <code>self.allKeys</code> 确实是</p>
<blockquote>
<p>"an array of all properties (each property as string)"</p>
</blockquote>
<p>那么您可能应该得到数组对象(属性)的 <code>intValue</code>,因为 <code>ABPropertyID</code> 只是一个 <code>typedef int32_t</code>。比如:</p>
<pre><code>currentFieldProperty = (ABPropertyID)[ intValue];
ABRecordCopyValue(currentRecordRef, currentFieldProperty)
</code></pre>
<p>但我们需要查看 <code>self.allKeys</code> 中的值或它的填充方式才能确定。</p>
<p>来自 <a href="http://developer.apple.com/library/ios/#DOCUMENTATION/AddressBook/Reference/ABRecordRef_iPhoneOS/Reference/reference.html" rel="noreferrer noopener nofollow">ABRecordRef Reference</a>和 <a href="http://developer.apple.com/library/mac/#documentation/CoreFoundation/Reference/CFTypeRef/Reference/reference.html" rel="noreferrer noopener nofollow">CFTypeRef Reference</a> </p>
<blockquote>
<p><code>ABRecordCopyValue</code> - <em>Returns the value of a record property.</em></p>
<pre><code> CFTypeRef ABRecordCopyValue (
ABRecordRef record,
ABPropertyID property
);
</code></pre>
<p><strong>Parameters</strong><br/>
<code>record</code> - <em>The record containing the property in question.</em><br/>
<code>property</code> - <em>The property of record whose value is being returned.</em><br/></p>
<p><strong>Return Value</strong><br/>
<em>The value of property in record.</em></p>
</blockquote>
<p>还有:</p>
<blockquote>
<p><code>ABPropertyID</code> - <em>Integer that identifies a record property.</em><br/>
<code>typedef int32_t ABPropertyID;</code></p>
</blockquote>
<hr/>
<p> - 以及更多故障排除想法 -</p>
<p>如果不是上述情况,那么当你在 <code>(NSString*)ABRecordCopyValue(currentRecordRef, currentFieldProperty)</code> 所以这里有一个小辅助函数可以解决这个问题:</p>
<pre><code>- (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 = ;
} else if (cfType == AXUIElementGetTypeID()) {
stringValue = [ description];
} else if (cfType == AXValueGetTypeID()) {
stringValue = ;
} else if (cfType == CFArrayGetTypeID()) {
stringValue = ;
} else if (cfType == CFBooleanGetTypeID()) {
stringValue = CFBooleanGetValue(cfValue) ? @"YES" : @"NO";
} else {
CFStringRef description = CFCopyDescription(cfValue);
stringValue = [(id)CFMakeCollectable(description) autorelease];
}
return stringValue;
}
</code></pre>
<p>然后执行 <code>currentRecord = ;</code> 并检查以确保 <code>self.allKeys</code> 在索引 <code>j 处有一个对象</code> 和 <code>self.allContacts</code> 在索引 <code>i</code> 处有一个对象:</p>
<pre><code>NSString *currentRecord = [ init];
ABRecordRef currentRecordRef;
ABPropertyID currentFieldProperty;
if (self.allContacts.count > i) {
currentRecordRef = (ABRecordRef);
if (self.allKeys.count > j) {
currentFieldProperty = (ABPropertyID);
currentRecord = ;
} else {
NSLog(@"self.allKeys has no value at index (%d): %@", j, );
}
} else {
NSLog(@"self.allContacts has no value at index (%d): %@", i, );
}
</code></pre>
<hr/>
<p>编辑(关于评论):</p>
<p>要将属性名称的字符串转换为其 int 值,您需要创建以下内容(这可能不是它们需要的正确顺序,因此 <code>NSLog</code> 他们先看看什么他们需要的顺序):</p>
<pre><code>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;
}
- (ABPropertyID)stringToABPropertyID:(NSString *)propertyString {
int retVal;
for(int i=0; i < sizeof(ABPropertyID_toString) - 1; ++i) {
if([(NSString *)ABPropertyID_toString isEqual:propertyString]) {
retVal = i;
break;
}
}
return retVal;
}
</code></pre>
<p>然后传递 <code>stringToABPropertyID:</code> 数组 <code></code> 中的值,您将返回一个 <code>ABPropertyID</code>:</p>
<pre><code>currentFieldProperty = ];
</code></pre></p>
<p style="font-size: 20px;">关于iphone - ABRecordCopyValue 和 ABPropertyID 崩溃,我们在Stack Overflow上找到一个类似的问题:
<a href="https://stackoverflow.com/questions/7746111/" rel="noreferrer noopener nofollow" style="color: red;">
https://stackoverflow.com/questions/7746111/
</a>
</p>
页:
[1]