I am trying to create a Application which lists all contacts from the iPhone address book with the following code (coffeescript)
listContacts: ->
options = new ContactFindOptions()
options.filter = '';
options.multiple = true
fields = ["id", "photos", "name", "phoneNumbers"]
navigator.contacts.find(fields, @onSuccess, @onError, options)
onSuccess: (contacts) ->
console.log contacts.length
onError: (error) ->
console.log error
this seems to work nice for a bunch of contacts. but with 3000 the contacts will never return. the funny thing though this works perfectly on the iOsSimulator.
are there any limitations to the number of contacts which can be retrieved?
I had the same problem with 300 contacts, it took around 5 minutes. After I patched it only takes 10 seconds.
Here is my pull request : https://github.com/phonegap/phonegap/pull/19
They have to generate a temp file for each picture and they are using a crazy loop to find a free file path. Something like :
do {
filePath = [NSString stringWithFormat:@"%@/photo_%03d.jpg", docsPath, i++];
} while ([fileMgr fileExistsAtPath:filePath]);
Now I use mktemp and everything is faster.
If you don't need full res pictures, you can also replace :
CFDataRef photoData = ABPersonCopyImageData(self.record);
by :
CFDataRef photoData = ABPersonCopyImageDataWithFormat(self.record, kABPersonImageFormatThumbnail);
I hope that'll help you !
Edit :
IOS'll flush the temp directory each time you start the application:
You are responsible for deleting any temporary files that you created. The system will clean them up at startup, but that could be a very long time away.
From: http://cocoadev.com/wiki/NSTemporaryDirectory
If you don't want to slow down the bootstrap of your application, you should use always the same filepath based on the contact id. You'll save cleanup and write time if the file already exists :
- (NSObject*)extractPhotos
{
NSMutableArray* photos = nil;
if (ABPersonHasImageData(self.record)) {
//CFDataRef photoData = ABPersonCopyImageDataWithFormat(self.record, kABPersonImageFormatThumbnail);
CFDataRef photoData = ABPersonCopyImageData(self.record);
NSData* data = (__bridge NSData*)photoData;
// write to temp directory and store URI in photos array
// get the temp directory path
NSString* docsPath = [NSTemporaryDirectory ()stringByStandardizingPath];
NSError* err = nil;
int recordId = ABRecordGetRecordID(self.record);
NSFileManager* fileMgr = [[NSFileManager alloc] init];
NSString* filePath = [NSString stringWithFormat:@"%@/photo_%03d.jpg", docsPath, recordId];
BOOL hasImage = NO;
if ([fileMgr fileExistsAtPath:filePath]) {
hasImage = YES;
} else if ([data writeToFile:filePath options:NSAtomicWrite error:&err]) {
hasImage = YES;
}
if (hasImage) {
photos = [NSMutableArray arrayWithCapacity:1];
NSMutableDictionary* newDict = [NSMutableDictionary dictionaryWithCapacity:2];
[newDict setObject:filePath forKey:kW3ContactFieldValue];
[newDict setObject:@"url" forKey:kW3ContactFieldType];
[newDict setObject:@"false" forKey:kW3ContactFieldPrimary];
[photos addObject:newDict];
}
CFRelease(photoData);
}
return photos;
}
Edit (08/01/2013): FYI : merged in cordova : http://git-wip-us.apache.org/repos/asf/cordova-ios/commit/c6a1dbe3
First you have to add plugin from terminal command line
$ cordova plugin add org.apache.cordova.contacts
onDeviceReady you can call a method to open contact list
function chooseContact() {
var options = new ContactFindOptions();
options.fields = ["displayName", "name", "emails", "phoneNumbers"];
navigator.contacts.chooseContact(onSuccess, options);
}
function onSuccess(id, contact) {
console.log(JSON.stringify(contact));
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With