[CNContact] contact loading time optimised

This commit is contained in:
Brieuc Viel 2017-11-23 16:36:58 +01:00
parent bf0ae9a61e
commit dfc5af3c7f
7 changed files with 135 additions and 96 deletions

View file

@ -29,74 +29,60 @@
_sipAddresses = [[NSMutableArray alloc] init];
_emails = [[NSMutableArray alloc] init];
if (_person) {
_identifier = _person.identifier;
_firstName = _person.givenName;
_lastName = _person.familyName;
_displayName = [NSString stringWithFormat:@"%@ %@", _firstName, _lastName];
for (CNLabeledValue<CNPhoneNumber *> *phoneNumber in _person.phoneNumbers) {
[_phones addObject:phoneNumber.value.stringValue];
}
if ([_person respondsToSelector:NSSelectorFromString(
CNInstantMessageAddressUsernameKey)] ||
[_person respondsToSelector:NSSelectorFromString(
CNContactInstantMessageAddressesKey)]) {
if (_person.instantMessageAddresses != NULL) {
for (CNLabeledValue<CNInstantMessageAddress *> *sipAddr in _person
.instantMessageAddresses) {
[_sipAddresses addObject:sipAddr.value.username];
}
}
}
for (CNLabeledValue<NSString *> *email in _person.emailAddresses) {
[_emails addObject:email.value];
}
const char *key =
[NSString stringWithFormat:@"ab%@", acncontact.identifier].UTF8String;
// try to find friend associated with that person
_friend = linphone_friend_list_find_friend_by_ref_key(
linphone_core_get_default_friend_list(LC), key);
if (!_friend) {
_friend = linphone_friend_ref(linphone_core_create_friend(LC));
linphone_friend_set_ref_key(_friend, key);
linphone_friend_set_name(
_friend,
[NSString
stringWithFormat:@"%@%@", _firstName ? _firstName : @"",
_lastName
? [_firstName ? @" " : @""
stringByAppendingString:_lastName]
: @""]
.UTF8String);
for (NSString *sipAddr in _sipAddresses) {
LinphoneAddress *addr =
linphone_core_interpret_url(LC, sipAddr.UTF8String);
if (addr) {
linphone_address_set_display_name(addr,
[self displayName].UTF8String);
linphone_friend_add_address(_friend, addr);
linphone_address_destroy(addr);
}
}
for (NSString *phone in _phones) {
linphone_friend_add_phone_number(_friend, phone.UTF8String);
}
if (_friend) {
linphone_friend_enable_subscribes(_friend, FALSE);
linphone_friend_set_inc_subscribe_policy(_friend, LinphoneSPDeny);
linphone_core_add_friend(LC, _friend);
}
}
linphone_friend_ref(_friend);
_identifier = _person.identifier;
_firstName = _person.givenName;
_lastName = _person.familyName;
_displayName = [NSString stringWithFormat:@"%@ %@", _firstName, _lastName];
for (CNLabeledValue<CNPhoneNumber *> *phoneNumber in _person.phoneNumbers) {
[_phones addObject:phoneNumber.value.stringValue];
}
if ([_person respondsToSelector:NSSelectorFromString( CNInstantMessageAddressUsernameKey)] || [_person respondsToSelector:NSSelectorFromString(CNContactInstantMessageAddressesKey)]) {
if (_person.instantMessageAddresses != NULL) {
for (CNLabeledValue<CNInstantMessageAddress *> *sipAddr in _person.instantMessageAddresses) {
[_sipAddresses addObject:sipAddr.value.username];
}
}
}
for (CNLabeledValue<NSString *> *email in _person.emailAddresses) {
[_emails addObject:email.value];
}
const char *key = [NSString stringWithFormat:@"ab%@", acncontact.identifier].UTF8String;
// try to find friend associated with that person
_friend = linphone_friend_list_find_friend_by_ref_key(linphone_core_get_default_friend_list(LC), key);
if (!_friend) {
_friend = linphone_friend_ref(linphone_core_create_friend(LC));
linphone_friend_set_ref_key(_friend, key);
linphone_friend_set_name(_friend, [NSString stringWithFormat:@"%@%@", _firstName ? _firstName : @"", _lastName ? [_firstName ? @" " : @"" stringByAppendingString:_lastName] : @""] .UTF8String);
for (NSString *sipAddr in _sipAddresses) {
LinphoneAddress *addr = linphone_core_interpret_url(LC, sipAddr.UTF8String);
if (addr) {
linphone_address_set_display_name(addr, [self displayName].UTF8String);
linphone_friend_add_address(_friend, addr);
linphone_address_destroy(addr);
}
}
for (NSString *phone in _phones) {
linphone_friend_add_phone_number(_friend, phone.UTF8String);
}
if (_friend) {
linphone_friend_enable_subscribes(_friend, FALSE);
linphone_friend_set_inc_subscribe_policy(_friend, LinphoneSPDeny);
linphone_core_add_friend(LC, _friend);
}
}
linphone_friend_ref(_friend);
} else if (_friend) {
[self loadFriend];
[self loadFriend];
} else {
LOGE(@"Contact cannot be initialized");
return nil;
LOGE(@"Contact cannot be initialized");
return nil;
}
LOGI(@"Contact %@ %@ initialized with %d phones, %d sip, %d emails",
/* LOGI(@"Contact %@ %@ initialized with %d phones, %d sip, %d emails",
self.firstName ?: @"", self.lastName ?: @"", self.phones.count,
self.sipAddresses.count, self.emails.count);
*/
return self;
}

View file

@ -110,7 +110,7 @@ static int ms_strcmpfuz(const char *fuzzy_word, const char *sentence) {
}
- (NSString *)displayNameForContact:(Contact *)person {
NSString *name = [FastAddressBook displayNameForContact:person];
NSString *name = person.displayName;
if (name != nil && [name length] > 0 && ![name isEqualToString:NSLocalizedString(@"Unknown", nil)]) {
// Add the contact only if it fuzzy match filter too (if any)
if ([ContactSelection getNameOrEmailFilter] == nil ||
@ -119,18 +119,22 @@ static int ms_strcmpfuz(const char *fuzzy_word, const char *sentence) {
// Sort contacts by first letter. We need to translate the name to ASCII first, because of UTF-8
// issues. For instance expected order would be: Alberta(A tilde) before ASylvano.
NSData *name2ASCIIdata = [name dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES];
/* NSData *name2ASCIIdata = [name dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES];
NSString *name2ASCII = [[NSString alloc] initWithData:name2ASCIIdata encoding:NSASCIIStringEncoding];
return name2ASCII;
*/ return name;
}
}
return nil;
}
// TODO - check this
- (void)loadData {
_ongoing = TRUE;
LOGI(@"Load contact list");
NSString* previous = [PhoneMainView.instance getPreviousViewName];
addressBookMap = [LinphoneManager.instance getLinphoneManagerAddressBookMap];
BOOL updated = [LinphoneManager.instance getContactsUpdated];
if(([previous isEqualToString:@"ContactsDetailsView"] && updated)|| [addressBookMap count] == 0){
[LinphoneManager.instance setContactsUpdated:FALSE];
@synchronized(addressBookMap) {
//Set all contacts from ContactCell to nil
for (NSInteger j = 0; j < [self.tableView numberOfSections]; ++j)
@ -224,6 +228,8 @@ static int ms_strcmpfuz(const char *fuzzy_word, const char *sentence) {
}
});
}
[LinphoneManager.instance setLinphoneManagerAddressBookMap:addressBookMap];
}
_ongoing = FALSE;
}
@ -433,7 +439,10 @@ static int ms_strcmpfuz(const char *fuzzy_word, const char *sentence) {
selector:@selector(onAddressBookUpdate:)
name:kLinphoneAddressBookUpdate
object:nil];
[self loadData];
dispatch_async(dispatch_get_main_queue(),
^{
[self loadData];
});
}
}

View file

@ -33,7 +33,7 @@
#include "linphone/linphonecore.h"
#include "bctoolbox/list.h"
#import "OrderedDictionary.h"
#import "ProviderDelegate.h"
extern NSString *const LINPHONERC_APPLICATION_KEY;
@ -197,6 +197,13 @@ typedef struct _LinphoneManagerSounds {
- (void)shouldPresentLinkPopup;
- (void)setProviderDelegate:(ProviderDelegate *)del;
- (void) setLinphoneManagerAddressBookMap:(OrderedDictionary*) addressBook;
- (OrderedDictionary*) getLinphoneManagerAddressBookMap;
- (void) setContactsUpdated:(BOOL) updated;
- (BOOL) getContactsUpdated;
@property ProviderDelegate *providerDelegate;
@property (readonly) BOOL isTesting;
@ -225,5 +232,7 @@ typedef struct _LinphoneManagerSounds {
@property BOOL nextCallIsTransfer;
@property BOOL conf;
@property NSDictionary *pushDict;
@property(strong, nonatomic) OrderedDictionary *linphoneManagerAddressBookMap;
@property (nonatomic, assign) BOOL contactsUpdated;
@end

View file

@ -257,7 +257,7 @@ struct codec_name_pref_table codec_pref_table[] = {{"speex", 8000, "speex_8k_pre
_bluetoothEnabled = FALSE;
_conf = FALSE;
_fileTransferDelegates = [[NSMutableArray alloc] init];
_linphoneManagerAddressBookMap = [[OrderedDictionary alloc] init];
pushCallIDs = [[NSMutableArray alloc] init];
_photoLibrary = [[ALAssetsLibrary alloc] init];
_isTesting = [LinphoneManager isRunningTests];
@ -292,6 +292,23 @@ struct codec_name_pref_table codec_pref_table[] = {{"speex", 8000, "speex_8k_pre
[NSNotificationCenter.defaultCenter removeObserver:self];
}
#pragma mark - AddressBookMap
- (void) setLinphoneManagerAddressBookMap:(OrderedDictionary*) addressBook{
_linphoneManagerAddressBookMap = addressBook;
}
- (OrderedDictionary*) getLinphoneManagerAddressBookMap{
return _linphoneManagerAddressBookMap;
}
- (void) setContactsUpdated:(BOOL) updated{
_contactsUpdated = updated;
}
- (BOOL) getContactsUpdated{
return _contactsUpdated;
}
#pragma deploymate push "ignored-api-availability"
- (void)silentPushFailed:(NSTimer *)timer {
if (_silentPushCompletion) {

View file

@ -79,6 +79,7 @@
@property(nonatomic, strong) IBOutlet UICompositeView *mainViewController;
@property(nonatomic, strong) NSString *currentName;
@property(nonatomic, strong) NSString *previousView;
@property(nonatomic, strong) NSString *name;
@property(weak, readonly) UICompositeViewDescription *currentView;
@property LinphoneChatRoom* currentRoom;
@ -87,6 +88,9 @@
- (void)changeCurrentView:(UICompositeViewDescription *)view;
- (UIViewController*)popCurrentView;
- (UIViewController *)popToView:(UICompositeViewDescription *)currentView;
- (void) setPreviousViewName:(NSString*)previous;
- (NSString*) getPreviousViewName;
+ (NSString*) getPreviousViewName;
- (UICompositeViewDescription *)firstView;
- (void)hideStatusBar:(BOOL)hide;
- (void)hideTabBar:(BOOL)hide;

View file

@ -128,6 +128,7 @@ static RootViewManager *rootViewManagerInstance = nil;
currentView = nil;
_currentRoom = NULL;
_currentName = NULL;
_previousView = nil;
inhibitedEvents = [[NSMutableArray alloc] init];
}
@ -657,6 +658,7 @@ static RootViewManager *rootViewManagerInstance = nil;
PhoneMainView *vc = [[RootViewManager instance] setViewControllerForDescription:view];
if (![view equal:vc.currentView] || vc != self) {
LOGI(@"Change current view to %@", view.name);
[self setPreviousViewName:vc.currentView.name];
NSMutableArray *viewStack = [RootViewManager instance].viewDescriptionStack;
[viewStack addObject:view];
if (animated && transition == nil)
@ -683,6 +685,19 @@ static RootViewManager *rootViewManagerInstance = nil;
return [self _changeCurrentView:view transition:[PhoneMainView getBackwardTransition] animated:ANIMATED];
}
- (void) setPreviousViewName:(NSString*)previous{
_previousView = previous;
}
- (NSString*) getPreviousViewName {
return _previousView;
}
+ (NSString*) getPreviousViewName {
return [self getPreviousViewName];
}
- (UICompositeViewDescription *)firstView {
UICompositeViewDescription *view = nil;
NSArray *viewStack = [RootViewManager instance].viewDescriptionStack;

View file

@ -91,8 +91,7 @@
+ (NSString *)normalizeSipURI:(NSString *)address {
// replace all whitespaces (non-breakable, utf8 nbsp etc.) by the "classical" whitespace
NSString *normalizedSipAddress = [[address
componentsSeparatedByCharactersInSet:[NSCharacterSet whitespaceCharacterSet]] componentsJoinedByString:@" "];
NSString *normalizedSipAddress = nil;
LinphoneAddress *addr = linphone_core_interpret_url(LC, [address UTF8String]);
if (addr != NULL) {
linphone_address_clean(addr);
@ -100,8 +99,11 @@
normalizedSipAddress = [NSString stringWithUTF8String:tmp];
ms_free(tmp);
linphone_address_destroy(addr);
return normalizedSipAddress;
}else {
normalizedSipAddress = [[address componentsSeparatedByCharactersInSet:[NSCharacterSet whitespaceCharacterSet]] componentsJoinedByString:@" "];
return normalizedSipAddress;
}
return normalizedSipAddress;
}
+ (BOOL)isAuthorized {
@ -112,8 +114,10 @@
if ((self = [super init]) != nil) {
store = [[CNContactStore alloc] init];
_addressBookMap = [NSMutableDictionary dictionary];
[self reloadAllContacts];
}
dispatch_async(dispatch_get_main_queue(), ^{
[self reloadAllContacts];
});
}
self.needToUpdate = FALSE;
if (floor(NSFoundationVersionNumber) >=
NSFoundationVersionNumber_iOS_9_x_Max) {
@ -167,13 +171,14 @@
error:&contactError];
NSArray *keysToFetch = @[
CNContactEmailAddressesKey, CNContactPhoneNumbersKey,
CNContactFamilyNameKey, CNContactGivenNameKey,
CNContactFamilyNameKey, CNContactGivenNameKey, CNContactNicknameKey,
CNContactPostalAddressesKey, CNContactIdentifierKey,
CNInstantMessageAddressUsernameKey, CNContactInstantMessageAddressesKey,
CNInstantMessageAddressUsernameKey, CNContactImageDataKey
];
CNContactFetchRequest *request =
[[CNContactFetchRequest alloc] initWithKeysToFetch:keysToFetch];
success =
[store enumerateContactsWithFetchRequest:request
error:&contactError
@ -183,10 +188,10 @@
NSLog(@"error fetching contacts %@",
contactError);
} else {
Contact *newContact = [[Contact alloc]
Contact *newContact = [[Contact alloc]
initWithCNContact:contact];
[self registerAddrsFor:newContact];
}
}
}];
// load Linphone friends
const MSList *lists = linphone_core_get_friends_lists(LC);
@ -214,25 +219,18 @@
}
- (void)registerAddrsFor:(Contact *)contact {
for (NSString *phone in contact.phones) {
char *normalizedPhone = linphone_proxy_config_normalize_phone_number(
linphone_core_get_default_proxy_config(LC), phone.UTF8String);
NSString *name = [FastAddressBook
normalizeSipURI:normalizedPhone
? [NSString stringWithUTF8String:normalizedPhone]
: phone];
if (phone != NULL) {
[_addressBookMap
setObject:contact
forKey:(name ?: [FastAddressBook localizedLabel:phone])];
}
if (normalizedPhone)
ms_free(normalizedPhone);
}
for (NSString *sip in contact.sipAddresses) {
[_addressBookMap setObject:contact
forKey:([FastAddressBook normalizeSipURI:sip] ?: sip)];
}
for (NSString *phone in contact.phones) {
char *normalizedPhone = linphone_proxy_config_normalize_phone_number(linphone_core_get_default_proxy_config(LC), phone.UTF8String);
NSString *name = [FastAddressBook normalizeSipURI:normalizedPhone ? [NSString stringWithUTF8String:normalizedPhone] : phone];
if (phone != NULL) {
[_addressBookMap setObject:contact forKey:(name ?: [FastAddressBook localizedLabel:phone])];
}
if (normalizedPhone)
ms_free(normalizedPhone);
}
for (NSString *sip in contact.sipAddresses) {
[_addressBookMap setObject:contact forKey:([FastAddressBook normalizeSipURI:sip] ?: sip)];
}
}
#pragma mark - Tools
@ -407,6 +405,7 @@
NSLog(@"Success %d",
[store executeSaveRequest:saveRequest error:&saveError]);
[self updateFriend:contact];
[LinphoneManager.instance setContactsUpdated:TRUE];
} @catch (NSException *exception) {
NSLog(@"=====>>>>> CNContact SaveRequest failed : description = %@",
[exception description]);