在我的应用程序中,Crashlytics用于收集用户的崩溃报告.这是来自用户的一个崩溃报告.它可能取决于用户的联系信息.我无法重建崩溃,因为我不知道他/她的联系人是什么.有没有人对这种情况有所了解?
com.apple.root.default-priority Crashed 0 CoreFoundation CFStringCreateCopy + 13 1 AppSupport CPsqliteDatabaseCreateWithPath + 36 2 AppSupport CPsqliteDatabaseCreateWithPath + 36 3 AppSupport CPRecordStoreGetDatabase + 16 4 AppSupport _getReaderConnection + 10 5 AppSupport CPRecordStoreProcessQueryWithBindBlock + 22 6 AppSupport CPRecordStoreCopyAllInstancesOfClassWhereWithBindBlock + 98 7 AddressBook ABCCopyArrayOfAllPeopleInSourceWithSortOrdering + 244 8 SeeYouKee PhoneNumberInputViewController.m line 538-[PhoneNumberInputViewController dofetchContacts:] 9 AddressBook __37-[ABTCC accessRequestWithCompletion:]_block_invoke_0 + 26 10 TCC __TCCAccessRequest_block_invoke_038 + 316 11 ... libxpc.dylib _xpc_connection_call_reply + 26 12 libdispatch.dylib _dispatch_root_queue_drain + 278 13 libdispatch.dylib _dispatch_worker_thread2 + 92 14 libsystem_c.dylib _pthread_wqthread + 360
8 SeeYouKee PhoneNumberInputViewController.m第538行的代码 – [PhoneNumberInputViewController dofetchContacts:]
是:
NSArray *contactsInAddressBook = CFBridgingRelease(ABAddressBookCopyArrayOfAllPeopleInSourceWithSortOrdering(addressBook,nil,kABPersonSortByLastName));
编辑1
-(void)dofetchContacts:(ABAddressBookRef)addressBook{ NSMutableArray *contactMutArr = [NSMutableArray array]; NSMutableString *mStrOfContacts = [NSMutableString string]; NSArray *contactsInAddressBook = CFBridgingRelease(ABAddressBookCopyArrayOfAllPeopleInSourceWithSortOrdering(addressBook,kABPersonSortByLastName)); if (ABPersonGetCompositeNameFormat() == kABPersonCompositeNameFormatLastNameFirst) { for (id aPerson in contactsInAddressBook) { ABRecordRef person = (__bridge ABRecordRef)(aPerson); ABMultiValueRef phoneMultiValue = ABRecordCopyValue(person,kABPersonPhoneProperty); ABMultiValueRef emailMultiValue = ABRecordCopyValue(person,kABPersonEmailProperty); int countPhone = 0; int countEmail = 0; NSMutableArray *phoneStrArr; NSMutableArray *emailStrArr; if (phoneMultiValue != NULL) { countPhone = ABMultiValueGetCount(phoneMultiValue); } if (emailMultiValue != NULL) { countEmail = ABMultiValueGetCount(emailMultiValue); } if (countEmail>0) { emailStrArr = [NSMutableArray array]; for (int i = 0; i < countEmail; i++) { CFStringRef anEmailCF = ABMultiValueCopyValueAtIndex(emailMultiValue,i); NSString *anEmail = (__bridge NSString *)anEmailCF; [emailStrArr addObject:anEmail]; if (anEmailCF != NULL)CFRelease(anEmailCF); } } if (countPhone > 0) { phoneStrArr = [NSMutableArray array]; for (int i = 0; i < countPhone; i++) { CFStringRef anPhoneCF = ABMultiValueCopyValueAtIndex(phoneMultiValue,i); NSString *anPhone = (__bridge NSString *)anPhoneCF; NSCharacterSet *cs = [[NSCharacterSet characterSetWithCharactersInString:@"0123456789"] invertedSet]; NSString *anPhonePureNumber = [[anPhone componentsSeparatedByCharactersInSet:cs] componentsJoinedByString:@""]; [phoneStrArr addObject:anPhonePureNumber]; if (anPhoneCF != NULL)CFRelease(anPhoneCF); } } // if (arrRefOfEmails != NULL)CFRelease(arrRefOfEmails); CFStringRef lastNameMultiValueCF = ABRecordCopyValue(person,kABPersonLastNameProperty); CFStringRef firstNmaeMultiValueCF = ABRecordCopyValue(person,kABPersonFirstNameProperty); CFStringRef middleNmaeMultiValueCF = ABRecordCopyValue(person,kABPersonMiddleNameProperty); NSString *lastNameMultiValue = (__bridge NSString *)lastNameMultiValueCF; NSString *firstNmaeMultiValue = (__bridge NSString *)firstNmaeMultiValueCF; NSString *middleNmaeMultiValue = (__bridge NSString *)middleNmaeMultiValueCF; NSString *name = [NSString stringWithFormat:@"%@%@%@",(![lastNameMultiValue length])?@"":lastNameMultiValue,(![middleNmaeMultiValue length])?@"":middleNmaeMultiValue,(![firstNmaeMultiValue length])?@"":firstNmaeMultiValue]; if (lastNameMultiValueCF != NULL)CFRelease(lastNameMultiValueCF); if (firstNmaeMultiValueCF != NULL)CFRelease(firstNmaeMultiValueCF); if (middleNmaeMultiValueCF != NULL)CFRelease(middleNmaeMultiValueCF); CFDataRef anAvatarCF = ABPersonCopyImageDataWithFormat(person,kABPersonImageFormatThumbnail); NSData *anAvatarData = (__bridge NSData *)anAvatarCF; UIImage *anAvatar = [UIImage imageWithData:anAvatarData]; if (anAvatarCF != NULL)CFRelease(anAvatarCF); NSDictionary *aPersonDict = [NSDictionary dictionaryWithObjectsAndKeys:name,@"name",[phoneStrArr componentsJoinedByString:@"; "],@"phoneNumber",[emailStrArr componentsJoinedByString:@"; "],@"email",anAvatar,@"avatar",nil]; [contactMutArr addObject:aPersonDict]; NSLog(@"------phoneStrArr :%@",phoneStrArr); NSString *enPhoneNumber = @""; if (phoneStrArr) { enPhoneNumber = [EncryptWithMD5 encryptWithMD5: [phoneStrArr componentsJoinedByString:@"; "]]; } [mStrOfContacts appendString:enPhoneNumber]; [mStrOfContacts appendString:@","]; if (phoneMultiValue != NULL)CFRelease(phoneMultiValue); if (emailMultiValue != NULL)CFRelease(emailMultiValue); } }else{ for (id aPerson in contactsInAddressBook) { ABRecordRef person = (__bridge ABRecordRef)(aPerson); ABMultiValueRef phoneMultiValue = ABRecordCopyValue(person,kABPersonEmailProperty); int countEmail = 0; NSMutableArray *emailStrArr; NSMutableArray *phoneStrArr; if (emailMultiValue != NULL) { countEmail = ABMultiValueGetCount(emailMultiValue); } if (countEmail>0) { emailStrArr = [NSMutableArray array]; for (int i = 0; i < countEmail; i++) { CFStringRef anEmailCF = ABMultiValueCopyValueAtIndex(emailMultiValue,i); NSString *anEmail = (__bridge NSString *)anEmailCF; [emailStrArr addObject:anEmail]; if (anEmailCF != NULL)CFRelease(anEmailCF); } } int count = ABMultiValueGetCount(phoneMultiValue); if (count > 0) { phoneStrArr = [NSMutableArray array]; for (int i = 0; i < count; i++) { CFStringRef anPhoneCF = ABMultiValueCopyValueAtIndex(phoneMultiValue,i); NSString *anPhone = (__bridge NSString *)anPhoneCF; NSCharacterSet *cs = [[NSCharacterSet characterSetWithCharactersInString:@"0123456789"] invertedSet]; NSString *anPhonePureNumber = [[anPhone componentsSeparatedByCharactersInSet:cs] componentsJoinedByString:@""]; [phoneStrArr addObject:anPhonePureNumber]; if (anPhoneCF != NULL)CFRelease(anPhoneCF); } } CFStringRef lastNameMultiValueCF = ABRecordCopyValue(person,(![firstNmaeMultiValue length])?@"":firstNmaeMultiValue,(![lastNameMultiValue length])?@"":lastNameMultiValue]; if (lastNameMultiValueCF != NULL)CFRelease(lastNameMultiValueCF); if (firstNmaeMultiValueCF != NULL)CFRelease(firstNmaeMultiValueCF); if (middleNmaeMultiValueCF != NULL)CFRelease(middleNmaeMultiValueCF); CFDataRef anAvatarCF = ABPersonCopyImageDataWithFormat(person,nil]; [contactMutArr addObject:aPersonDict]; NSString *enPhoneNumber = [EncryptWithMD5 encryptWithMD5: [phoneStrArr componentsJoinedByString:@"; "]]; [mStrOfContacts appendString:enPhoneNumber]; [mStrOfContacts appendString:@","]; if (phoneMultiValue != NULL)CFRelease(phoneMultiValue); if (emailMultiValue != NULL)CFRelease(emailMultiValue); } } self.contactArr = [[NSArray alloc] initWithArray: contactMutArr]; strOfContacts = [NSString stringWithString:mStrOfContacts]; }
编辑2
-(void)beginFetchContacts{ // Request authorization to Address Book ABAddressBookRef addressBookRef = NULL; if (ABAddressBookRequestAccessWithCompletion) { CFErrorRef *aError=nil; addressBookRef = ABAddressBookCreateWithOptions(NULL,aError); if (ABAddressBookGetAuthorizationStatus() == kABAuthorizationStatusNotDetermined) { ABAddressBookRequestAccessWithCompletion(addressBookRef,^(bool granted,CFErrorRef error) { // First time access has been granted,add the contact if (granted) { [self dofetchContacts:addressBookRef]; }else{ // [self alertActionSwitchOnTheContactsAccess]; [self buttonCancelPressed:nil]; } }); } else if (ABAddressBookGetAuthorizationStatus() == kABAuthorizationStatusAuthorized) { // The user has prevIoUsly given access,add the contact [self dofetchContacts:addressBookRef]; } }else{ addressBookRef = ABAddressBookCreate(); [self dofetchContacts:addressBookRef]; } if (addressBookRef != NULL)CFRelease(addressBookRef); }
解决方法
你可能是在调用ABAddressBookCopyArrayOfAllPeopleInSourceWithSortOrdering()的不同线程上调用ABAddressBookCreateWithOptions()和/或ABAddressBookRequestAccessWithCompletion()吗?
请注意Apple的API文档中的以下内容:
The completion handler is called on an arbitrary queue. If your app uses an address book throughout the app,you are responsible for ensuring that all usage of that address book is dispatched to a single queue to ensure correct thread-safe operation.
或者,检查以确保您没有过早地释放从ABAddressBookCreateWithOptions()返回的ABAddressBookRef.请记住,ABAddressBookRequestAccessWithCompletion()是异步的.