菜鸟教程小白 发表于 2022-12-12 17:42:13

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>&#34;an array of all properties (each property as string)&#34;</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) ? @&#34;YES&#34; : @&#34;NO&#34;;
    } 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 &gt; i) {
    currentRecordRef = (ABRecordRef);   
    if (self.allKeys.count &gt; j) {
      currentFieldProperty = (ABPropertyID);
      currentRecord = ;
    } else {
      NSLog(@&#34;self.allKeys has no value at index (%d): %@&#34;, j, );
    }
} else {
    NSLog(@&#34;self.allContacts has no value at index (%d): %@&#34;, i, );
}
</code></pre>

<hr/>

<p>编辑(关于评论):</p>

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

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

- (NSString *)ABPropertyIDToString:(ABPropertyID)propertyVal {
    return ABPropertyID_toString;
}

- (ABPropertyID)stringToABPropertyID:(NSString *)propertyString {
    int retVal;
    for(int i=0; i &lt; 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]
查看完整版本: iphone - ABRecordCopyValue 和 ABPropertyID 崩溃