alterplay / apaddressbook Goto Github PK
View Code? Open in Web Editor NEWEasy access to iOS address book
License: MIT License
Easy access to iOS address book
License: MIT License
Seems like a good open source project, would be great if the examples in objective-c and swift could build.
I'm using this in Swift project, basic functionality works pretty good, however when running self.addressBook.loadContacts(...)
for second or latter time(app was dismissed and after it's become active again, I want to reload contacts), changes in actual address book are not reflected...
seems like it needs to be included in the file APAddressBook-Bridging.h
What is the best way to get one contact based on RecordID? Is there a method for this? Or do I have to load the entire addressbook and filter based on the RecordID?
thank you!
I suggest adding a check on - (NSArray *)arrayProperty:(ABPropertyID)property fromRecord:(ABRecordRef)recordRef for kABPersonPhoneProperty if it's really an NSString.
i see there is nothing like that in the current release?
My app crashes running on my iPhone 6 with a large AddressBook but does not crash in the iOS 6 simulator with only a few entries in APAddressBook.m:117
peopleArrayRef = ABAddressBookCopyArrayOfAllPeople(self.addressBook);
Because:
Exception Type: EXC_BAD_ACCESS (SIGSEGV)
Exception Subtype: KERN_INVALID_ADDRESS at 0x0000000000000003
Triggered by Thread: 6
Thread 6 name: Dispatch queue: com.apple.root.default-qos
Thread 6 Crashed:
0 libsqlite3.dylib 0x000000019749006c 0x197444000 + 311404
1 libsqlite3.dylib 0x00000001974900cc 0x197444000 + 311500
2 libsqlite3.dylib 0x000000019748110c 0x197444000 + 250124
3 libsqlite3.dylib 0x000000019747fdf4 sqlite3_step + 524
4 AppSupport 0x000000018b5e7728 CPSqliteStatementSendResults + 72
5 AppSupport 0x000000018b5ecd08 CPRecordStoreProcessRecordStatementWithPropertyIndices + 188
6 AppSupport 0x000000018b5ed084 CPRecordStoreProcessQueryWithBindBlock + 128
7 AppSupport 0x000000018b5ed150 CPRecordStoreCopyAllInstancesOfClassWhereWithBindBlock + 136
8 AddressBook 0x000000018454ea28 ABCCopyArrayOfAllPeopleInSourceWithSortOrdering + 156
9 APAddressBook 0x00000001002b77b8 __48-[APAddressBook loadContactsOnQueue:completion:]_block_invoke (APAddressBook.m:117)
10 AddressBook 0x00000001845a3194 __37-[ABTCC accessRequestWithCompletion:]_block_invoke + 44
11 libdispatch.dylib 0x000000019776d990 _dispatch_call_block_and_release + 20
12 libdispatch.dylib 0x000000019776d950 _dispatch_client_callout + 12
13 libdispatch.dylib 0x000000019777a77c _dispatch_root_queue_drain + 1844
14 libdispatch.dylib 0x000000019777bc48 _dispatch_worker_thread3 + 104
15 libsystem_pthread.dylib 0x000000019794d228 _pthread_wqthread + 812
16 libsystem_pthread.dylib 0x000000019794ceec start_wqthread + 0
When the debugger breaks on frame 9 above:
(lldb) po self.addressBook
<ABCAddressBook 0x144d0b970 [0x197dc0f50]>
(lldb) po self
<APAddressBook: 0x1700533e0>
I enabled NSZombies objects in my scheme and it did nothing, but i noticed another thread with exeactly the same stack frames, see threads 2 and 6 below:
Hardware Model: iPhone7,2
Process: ABC [2876]
Path: /private/var/mobile/Containers/Bundle/Application/8E7B40EE-A4C2-4E09-8303-501BA3CF2FCC/ABC.app/ABC
Identifier: com.king7532.abc.ABC
Version: 99 (0.65)
Code Type: ARM-64 (Native)
Parent Process: launchd [1]
Date/Time: 2015-07-14 11:13:33.753 -0400
Launch Time: 2015-07-14 11:13:30.530 -0400
OS Version: iOS 8.4 (12H143)
Report Version: 105
Exception Type: EXC_BAD_ACCESS (SIGSEGV)
Exception Subtype: KERN_INVALID_ADDRESS at 0x0000000000000003
Triggered by Thread: 6
Thread 0 name: Dispatch queue: com.apple.main-thread
Thread 0:
0 UIKit 0x000000018a006ba8 -[UIViewController _isDeallocating] + 0
1 libobjc.A.dylib 0x000000019710a4b8 -[NSObject allowsWeakReference] + 20
2 libobjc.A.dylib 0x00000001971037e4 weak_register_no_lock + 140
3 libobjc.A.dylib 0x00000001971082cc objc_storeWeak + 212
4 ABC 0x00000001000eb5bc -[ZLPeoplePickerViewController setDelegate:] (ZLPeoplePickerViewController.h:48)
5 ABC 0x00000001001445a0 ABC.ABCContactsViewController.showPeoplePickerController (ABC.ABCContactsViewController)() -> () (ABCContactsViewController.swift:53)
6 ABC 0x0000000100146004 ABC.ABCContactsViewController.accessGrantedForAddressBook (ABC.ABCContactsViewController)() -> () (ABCContactsViewController.swift:185)
7 ABC 0x00000001001457e0 ABC.ABCContactsViewController.checkAddressBookAccess (ABC.ABCContactsViewController)() -> () (ABCContactsViewController.swift:153)
8 ABC 0x000000010014441c ABC.ABCContactsViewController.viewDidAppear (ABC.ABCContactsViewController)(Swift.Bool) -> () (ABCContactsViewController.swift:45)
9 ABC 0x000000010014446c @objc ABC.ABCContactsViewController.viewDidAppear (ABC.ABCContactsViewController)(Swift.Bool) -> () (ABCContactsViewController.swift:0)
10 UIKit 0x0000000189eb3f50 -[UIViewController _setViewAppearState:isAnimating:] + 588
11 UIKit 0x0000000189eb44bc -[UIViewController _endAppearanceTransition:] + 340
12 UIKit 0x000000018a1def1c __97-[UITabBarController transitionFromViewController:toViewController:transition:shouldSetSelected:]_block_invoke749 + 32
13 UIKit 0x0000000189f20268 -[UIViewController _executeAfterAppearanceBlock] + 60
14 UIKit 0x0000000189f201d0 _applyBlockToCFArrayCopiedToStack + 352
15 UIKit 0x0000000189e906a4 _afterCACommitHandler + 572
16 CoreFoundation 0x00000001853dc2a0 __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 28
17 CoreFoundation 0x00000001853d922c __CFRunLoopDoObservers + 356
18 CoreFoundation 0x00000001853d960c __CFRunLoopRun + 832
19 CoreFoundation 0x00000001853052d0 CFRunLoopRunSpecific + 392
20 GraphicsServices 0x000000018ed5b6f8 GSEventRunModal + 164
21 UIKit 0x0000000189f02f3c UIApplicationMain + 1484
22 ABC 0x000000010012d97c main (AppDelegate.swift:15)
23 libdyld.dylib 0x000000019779aa04 start + 0
Thread 1 name: Dispatch queue: com.apple.libdispatch-manager
Thread 1:
0 libsystem_kernel.dylib 0x0000000197898c24 kevent64 + 8
1 libdispatch.dylib 0x000000019777de6c _dispatch_mgr_invoke + 272
2 libdispatch.dylib 0x000000019776f998 _dispatch_mgr_thread + 48
Thread 2 name: Dispatch queue: com.apple.root.default-qos
Thread 2:
0 libsqlite3.dylib 0x000000019748ffa4 0x197444000 + 311204
1 libsqlite3.dylib 0x000000019748110c 0x197444000 + 250124
2 libsqlite3.dylib 0x000000019748110c 0x197444000 + 250124
3 libsqlite3.dylib 0x000000019747fdf4 sqlite3_step + 524
4 AppSupport 0x000000018b5e7728 CPSqliteStatementSendResults + 72
5 AppSupport 0x000000018b5ecd08 CPRecordStoreProcessRecordStatementWithPropertyIndices + 188
6 AppSupport 0x000000018b5ed084 CPRecordStoreProcessQueryWithBindBlock + 128
7 AppSupport 0x000000018b5ed150 CPRecordStoreCopyAllInstancesOfClassWhereWithBindBlock + 136
8 AddressBook 0x000000018454ea28 ABCCopyArrayOfAllPeopleInSourceWithSortOrdering + 156
9 APAddressBook 0x00000001002b77b8 __48-[APAddressBook loadContactsOnQueue:completion:]_block_invoke (APAddressBook.m:117)
10 AddressBook 0x00000001845a3194 __37-[ABTCC accessRequestWithCompletion:]_block_invoke + 44
11 libdispatch.dylib 0x000000019776d990 _dispatch_call_block_and_release + 20
12 libdispatch.dylib 0x000000019776d950 _dispatch_client_callout + 12
13 libdispatch.dylib 0x000000019777a77c _dispatch_root_queue_drain + 1844
14 libdispatch.dylib 0x000000019777bc48 _dispatch_worker_thread3 + 104
15 libsystem_pthread.dylib 0x000000019794d228 _pthread_wqthread + 812
16 libsystem_pthread.dylib 0x000000019794ceec start_wqthread + 0
Thread 3:
0 libsystem_kernel.dylib 0x00000001978b3c78 __workq_kernreturn + 8
1 libsystem_pthread.dylib 0x000000019794d2d8 _pthread_wqthread + 988
2 libsystem_pthread.dylib 0x000000019794ceec start_wqthread + 0
Thread 4:
0 libsystem_kernel.dylib 0x00000001978b3c78 __workq_kernreturn + 8
1 libsystem_pthread.dylib 0x000000019794d2d8 _pthread_wqthread + 988
2 libsystem_pthread.dylib 0x000000019794ceec start_wqthread + 0
Thread 5:
0 libsystem_kernel.dylib 0x00000001978b3c78 __workq_kernreturn + 8
1 libsystem_pthread.dylib 0x000000019794d2d8 _pthread_wqthread + 988
2 libsystem_pthread.dylib 0x000000019794ceec start_wqthread + 0
Thread 6 name: Dispatch queue: com.apple.root.default-qos
Thread 6 Crashed:
0 libsqlite3.dylib 0x000000019749006c 0x197444000 + 311404
1 libsqlite3.dylib 0x00000001974900cc 0x197444000 + 311500
2 libsqlite3.dylib 0x000000019748110c 0x197444000 + 250124
3 libsqlite3.dylib 0x000000019747fdf4 sqlite3_step + 524
4 AppSupport 0x000000018b5e7728 CPSqliteStatementSendResults + 72
5 AppSupport 0x000000018b5ecd08 CPRecordStoreProcessRecordStatementWithPropertyIndices + 188
6 AppSupport 0x000000018b5ed084 CPRecordStoreProcessQueryWithBindBlock + 128
7 AppSupport 0x000000018b5ed150 CPRecordStoreCopyAllInstancesOfClassWhereWithBindBlock + 136
8 AddressBook 0x000000018454ea28 ABCCopyArrayOfAllPeopleInSourceWithSortOrdering + 156
9 APAddressBook 0x00000001002b77b8 __48-[APAddressBook loadContactsOnQueue:completion:]_block_invoke (APAddressBook.m:117)
10 AddressBook 0x00000001845a3194 __37-[ABTCC accessRequestWithCompletion:]_block_invoke + 44
11 libdispatch.dylib 0x000000019776d990 _dispatch_call_block_and_release + 20
12 libdispatch.dylib 0x000000019776d950 _dispatch_client_callout + 12
13 libdispatch.dylib 0x000000019777a77c _dispatch_root_queue_drain + 1844
14 libdispatch.dylib 0x000000019777bc48 _dispatch_worker_thread3 + 104
15 libsystem_pthread.dylib 0x000000019794d228 _pthread_wqthread + 812
16 libsystem_pthread.dylib 0x000000019794ceec start_wqthread + 0
Thread 7:
0 libsystem_kernel.dylib 0x00000001978b3c78 __workq_kernreturn + 8
1 libsystem_pthread.dylib 0x000000019794d2d8 _pthread_wqthread + 988
2 libsystem_pthread.dylib 0x000000019794ceec start_wqthread + 0
Any help will be greatly appreciated. Thanks
Downloads/APAddressBook-master/Example/Swift/AddressBook/TableViewCell.swift:23:14: 'UIImageView?' does not have a member named 'image'
Downloads/APAddressBook-master/Example/Swift/AddressBook/TableViewCell.swift:24:14: 'UILabel?' does not have a member named 'text'
Downloads/APAddressBook-master/Example/Swift/AddressBook/TableViewCell.swift:25:14: 'UILabel?' does not have a member named 'text'
I had tried changing filter from phone to email and demo app crash.
When following these step
Please solve this ASAP
We're dealing with this problem http://stackoverflow.com/questions/11351454/dealing-with-duplicate-contacts-due-to-linked-cards-in-ios-address-book-api. Looking at the docs seems there's no way to filter those linked contacts using APAddressBook, is this true? Maybe I missed something?
If I use cocoapods 'use_frameworks' feature, the bridging header isn't included in the package, so it doesn't work. On the surface this is not a big problem, since I can just remove the use_frameworks string from my podfile. However, my other pods are depended on that thing, so it would be nice if there was a way to fix this.
I am trying to display the thumbnail images for address book contacts, and for some reason it recently stopped working.
When I use this code with a breakpoint inside the block, it never gets hit:
if let thumbnail = cell.apContact?.thumbnail
{
cell.leftIconImageView.image = thumbnail
}
I have verified that the contacts do in fact have thumbnails in my native Contacts app. I have also tried to use '.photo' instead of '.thumbnail' and still no luck.
It was working before just fine so not sure why the thumbnails are being ignored now. Everything else (i.e. names, emails, phone numbers) all load up just fine.
I think I updated the pod installation a week or so ago, so not sure if something changed since my initial use a couple months ago.
Any ideas?
I'm trying to sort the contacts at the same time as i'm reading the contacts, but it always returns an unsorted tableview. Is there maybe something that changed with the keys to sort for?
APAddressBook should have a method to get a contact given a RecordID, it should return a APContact object.
(Currently the only way to do this is to iterate all contacts - the AddressBook API gives the ABAddressBookGetPersonWithRecordID
function to return a ABRecordRef
which can be passed into the APContact initialiser.
If
then the program fails.
I believe the APContact should simply set the non-existent fields to a type of null value, if the field does not exist in the ABRecordRef.
Can you please add an example on how to load contacts with loadContactsOnQueue:completion: method.
self.addressBook.startObserveChangesWithCallback({() in
println("Address book change detected")
})
I added this code to my project, it's never being called. What am I doing wrong?
Thank you very much!
Downloads/APAddressBook-master/Example/Objective-C/AddressBook/ListViewController.m:78:37: No visible @interface for 'DTTableViewMemoryStorage' declares the selector 'addItems:'
What is the reason why a lot of available fields are missing in your framework? Would you be interested in a pull request that adds the missing fields?
I want to know if the library has a way to get the "Email Type" (home,work,iCloud,etc). If now i think is a good feature to develop..
Thx
Abel Osorio
I am trying to alert users when they need to enable permissions for my app to access their Contacts. I call 'loadAddressBookContacts()' in both 'viewDidLoad' and from an observer that listens for UIApplicationDidBecomeActiveNotification (for when a user leaves the app to update the permissions then comes back).
However, calling 'APAddressBook.access()' after the user has left the app and updated the permissions in settings does not seem to recognize the change and still returns the 'denied' status. Only after re-launching the app does the change get observed. Is this being cached somehow?
func loadAddressBookContacts()
{
// Check if access is denied
if APAddressBook.access() == APAddressBookAccess.Denied
{
self.displayAddressBookPermissionsAlert()
return
}
...load contacts...
}
when i loop through the contacts array and try to print the phone number its always nil. I have numbers stored in the simulator.
var book = APAddressBook()
book.fieldsMask = APContactField.All
book.loadContacts(
{(contacts:[AnyObject]!, error:NSError!) -> Void in
for c in contacts {
print (c.phoneNumber)
}
})
please add support for Carthage
Both in the sample code and app...when you test a change in the Address book access it crashed the app. To replicate:
Is there a way to get contacts of a group?
As far as I can tell, the pod is installed correctly, however, when I try and use "import APAddressBook", it says no such module.
I've tried adding and deleting the phone of a contact to see if the changes where refreshed (I'm retrieving contacts whith phone number as in the example given).
The callback was fired when a change like that was produced, but when I called listOfContacts I was receiving the same list of contacts as I had before the change... So I've ended up with this solution:
modifying APAddressBookExternalChangeCallback in APAddressBook.m by adding this line as first line:
ABAddressBookRevert(addressBookRef);
and now I obtain the refreshed list of contacts.
Greetings, and congratulations for your job!
Lucía.
there is a contact in AB usually marked as 'me'
Just a quick question. I've been wondering if it's possible to specify sort descriptors such that contacts that have the composite name, first name, and last name missing would be at the end of the array returned by loadContacts with the sort descriptor "firstName" ascending?
I'm trying to filter my contacts to remove those without an email address
where the example below works as expected for phone entries:
self.addressBook.filterBlock = {(contact: APContact!) -> Bool in
return contact.phones.count > 0
}
The following code returns "fatal error: unexpectedly found nil while unwrapping an Optional value"
self.addressBook.filterBlock = {(contact: APContact!) -> Bool in
return contact.emails.count > 0
}
How should the emails filter be implemented to avoid this error? I assume the [AnyObject]! emails and phones arrays contain different types so they should be treated differently, however the solution is not readily apparent to my noob eyes!
Feature request:
A method to delete contact from address book with recordId would be great.
Whether a contact has an address or not, I'm always seeing an empty addresses array in the filterBlock.
this is the code:
@IBOutlet weak var activity: UIActivityIndicatorView!
let addressBook = APAddressBook()
override func viewDidLoad() {
super.viewDidLoad()
self.registerCellClass(TableViewCell.self, forModelClass: APContact.self)
self.addressBook.fieldsMask = APContactField.FirstName | APContactField.LastName | APContactField.Emails
self.addressBook.sortDescriptors = [NSSortDescriptor(key: "firstName", ascending: true),
NSSortDescriptor(key: "lastName", ascending: true)]
self.addressBook.filterBlock = {(contact: APContact!) -> Bool in
println("\(contact.firstName), \(contact.lastName)")
return contact.emails != nil && contact.emails.count > 0
}
self.addressBook.loadContacts(
{ (contacts: [AnyObject]!, error: NSError!) in
self.activity.stopAnimating()
if (contacts != nil) {
self.memoryStorage().addItems(contacts)
}
else if (error != nil) {
let alert = UIAlertView(title: "Error", message: error.localizedDescription,
delegate: nil, cancelButtonTitle: "OK")
alert.show()
}
})
}
the result is a list with all contacts duplicated, why? do I need something more?
Both the Objective-c and Swift examples require running pod install.. the pod is local and shouldn't have to be installed.
when I changed
dispatch_async(self.localQueue, ^
{
ABAddressBookRegisterExternalChangeCallback(self.addressBook,
APAddressBookExternalChangeCallback,
(__bridge void *)(self));
});
to
dispatch_async(dispatch_get_main_queue(), ^
{
ABAddressBookRegisterExternalChangeCallback(self.addressBook,
APAddressBookExternalChangeCallback,
(__bridge void *)(self));
});
then it does call to the callback function but then the other errors will occur.
It looks like that APAddressBookExternalChangeCallback will be called on the thread that registered it then if we call register function with GCD then it can be a problem because we have no idea about how the system create, using and destroy threads for using with queue.
do you have any idea how to fix it.
cheers
Maybe it's just lack of knowledge but how can I encode a APContact to JSON in a easy way?
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:contacts options:0 error:nil];
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Invalid type in JSON write (APContact)'
Currently, if the app does not have access to the Address Book, it never asks for it. It only returns APAddressBookAccessUnknown
on [APAddressBook access]
.
You should add an API for requesting the access to the address book. Something like
+ (void)requestAccessWithCompletionBlock:(void(^)(void)block;
I've got the observer initialized in the ViewWillAppear method but it never finds any new changes to the addressbook. Removing or adding contacts.
Hi, I'm having trouble extracting the company info from my contacts. At the moment I iterate thought the Contacts list and pass a contact to a method to extract the first and last name and concatenate these into a string that is returned. However for entries that have no first and last name I'm trying to return the company instead.
However, contacts[i].company always returns nil
Feature request:
A method to generate a string from an instance of APAddress would be great. Ideally it would avoid null properties (such as missing Country Code).
Hello Alexey.
I found a bug.
Contact has no emails/phones (any arrays) but we try to retrieve it.
swift code to create contact: APContact(recordRef: person, fieldMask: .FirstName | .LastName | .Phones | .Emails) ->
[APContact enumerateMultiValueOfProperty:fromRecord:withBlock:] method ->
ABMultiValueRef multiValue = ABRecordCopyValue(recordRef, property);
multiValue is 0x0 in this case but we try to release it at CFRelease(multiValue);
So the the app crashes.
We need something like this:
if (multiValue != nil) { {
CFRelease(multiValue);
}
Thank you for your work!
Hi, thanks for the great tool. I needed to know if I can get birthday of contacts? My native contacts list do show birthday's of different contacts fetched from Facebook. But I don't see any property in APContact class regarding it.
NSData *data = (__bridge_transfer NSData *)ABPersonCopyImageDataWithFormat(recordRef, format);
is that ABPersonCopyImageDataWithFormat(recordRef, format) = nil. cause this
Hello,
Thanks for your work, I love APAddressBook and I'm using it in my almost-finished app!
I noticed a problem today while testing, the NSArray property of an APContact is always (null) also when in the contact library there is at least an email in it. Check out this screenshot with a contact example.
Here is my very simple code.
- (void)startLoading {
__block NSArray *arrayOfContacts = [NSArray new];
APAddressBook *addressBook = [[APAddressBook alloc] init];
addressBook.fieldsMask = APContactFieldFirstName | APContactFieldLastName | APContactFieldPhones | APContactFieldRecordID;
addressBook.sortDescriptors = @[
[NSSortDescriptor sortDescriptorWithKey:@"lastName" ascending:YES],
[NSSortDescriptor sortDescriptorWithKey:@"firstName" ascending:YES]];
[addressBook loadContacts:^(NSArray *contacts, NSError *error) {
if (!error) {
arrayOfContacts = contacts;
[contacts enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
APContact *current = (APContact *)obj;
NSLog(@"current email %@", current.emails);
}];
// Already here, contacts.emails is (null)
} else {
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:nil
message:error.localizedDescription
delegate:nil
cancelButtonTitle:@"OK"
otherButtonTitles:nil];
[alertView show];
}
}];
}
Am I doing something wrong or is this a problem in the APAddressBook library?
Thanks a lot.
You keep the wrapped ABAddressBookRef
private, but in order to call ABAddressBookRequestAccessWithCompletion
, we need to access it.
If you agree, I'm happy to submit a pull request. Thanks!
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.