diff --git a/Signal/src/contact/OWSContactsManager.m b/Signal/src/contact/OWSContactsManager.m index 40136a885..508078a69 100644 --- a/Signal/src/contact/OWSContactsManager.m +++ b/Signal/src/contact/OWSContactsManager.m @@ -207,28 +207,37 @@ void onAddressBookChanged(ABAddressBookRef notifyAddressBook, CFDictionaryRef in NSMutableDictionary *signalAccountMap = [NSMutableDictionary new]; NSMutableArray *signalAccounts = [NSMutableArray new]; NSArray *contacts = self.allContacts; + + // We use a transaction only to load the SignalRecipients for each contact, + // in order to avoid database deadlock. + NSMutableDictionary *> *contactIdToSignalRecipientsMap = + [NSMutableDictionary new]; [[TSStorageManager sharedManager].dbConnection readWithBlock:^(YapDatabaseReadTransaction *transaction) { for (Contact *contact in contacts) { NSArray *signalRecipients = [contact signalRecipientsWithTransaction:transaction]; - for (SignalRecipient *signalRecipient in - [signalRecipients sortedArrayUsingSelector:@selector(compare:)]) { - SignalAccount *signalAccount = [[SignalAccount alloc] initWithSignalRecipient:signalRecipient]; - signalAccount.contact = contact; - if (signalRecipients.count > 1) { - signalAccount.hasMultipleAccountContact = YES; - signalAccount.multipleAccountLabelText = - [[self class] accountLabelForContact:contact recipientId:signalRecipient.recipientId]; - } - if (signalAccountMap[signalAccount.recipientId]) { - DDLogInfo(@"Ignoring duplicate contact: %@, %@", signalAccount.recipientId, contact.fullName); - continue; - } - signalAccountMap[signalAccount.recipientId] = signalAccount; - [signalAccounts addObject:signalAccount]; - } + contactIdToSignalRecipientsMap[contact.uniqueId] = signalRecipients; } }]; + for (Contact *contact in contacts) { + NSArray *signalRecipients = contactIdToSignalRecipientsMap[contact.uniqueId]; + for (SignalRecipient *signalRecipient in [signalRecipients sortedArrayUsingSelector:@selector(compare:)]) { + SignalAccount *signalAccount = [[SignalAccount alloc] initWithSignalRecipient:signalRecipient]; + signalAccount.contact = contact; + if (signalRecipients.count > 1) { + signalAccount.hasMultipleAccountContact = YES; + signalAccount.multipleAccountLabelText = + [[self class] accountLabelForContact:contact recipientId:signalRecipient.recipientId]; + } + if (signalAccountMap[signalAccount.recipientId]) { + DDLogInfo(@"Ignoring duplicate contact: %@, %@", signalAccount.recipientId, contact.fullName); + continue; + } + signalAccountMap[signalAccount.recipientId] = signalAccount; + [signalAccounts addObject:signalAccount]; + } + } + dispatch_async(dispatch_get_main_queue(), ^{ self.signalAccountMap = [signalAccountMap copy]; self.signalAccounts = [signalAccounts copy];