Welcome!
This is the community forum for my apps Pythonista and Editorial.
For individual support questions, you can also send an email. If you have a very short question or just want to say hello — I'm @olemoritz on Twitter.
Contacts module: Access profile picture
-
Hi,
Is there a way to use the
contacts
module to get and edit profile pictures for iOS contacts?I'm sure I'd be able to do that with
objc_util
, but before I'd like to try if it can be done using the built incontacts
module -
I'm not sure you'd be able to with objc_util. I don't know if apps are allowed to have this kind of write access to contacts.
-
The
contacts
module currently doesn't expose that functionality (still on my todo list).It's definitely possible to do this with
objc_util
/ctypes
, but I don't think it would be possible to mix and match this approach with thecontacts
module. You can't get at the pointers to the underlying data structures incontacts
, so if you want to edit a profile picture of a person usingobjc_util
, you also have to find the right person object using that, and can't use the simplercontacts
interface.I'll see if I can come up with an example, not completely sure how much code is required right now.
-
Okay, here's some sample code that shows how to use
objc_util
with the Contacts framework to:- Find a person by name
- Access its picture, and convert it to a
ui.Image
to show it in the console - Set a new picture (picked from photos here, but you could of course also get this elsewhere)
- Save the changes
Before you run the example, set the
CONTACT_NAME
variable (near the top) to a name of someone in your contacts (or create a contact named "John Doe").from objc_util import * from ctypes import string_at import contacts import ui import photos # CHANGE THIS: CONTACT_NAME = 'John Doe' # Easier to do the authorization with the contacts module (this also authorizes the Contacts.framework): if not contacts.is_authorized(): # This implicitly shows the permission dialog, if necessary: contacts.get_all_groups() # Load classes we need from Contacts.framework: NSBundle.bundleWithPath_('/System/Library/Frameworks/Contacts.framework').load() CNContactStore = ObjCClass('CNContactStore') CNContact = ObjCClass('CNContact') CNSaveRequest = ObjCClass('CNSaveRequest') def main(): store = CNContactStore.alloc().init().autorelease() # Find the first contact that matches the name. pred = CNContact.predicateForContactsMatchingName_(CONTACT_NAME) fetch_keys = ['imageDataAvailable', 'imageData'] people = store.unifiedContactsMatchingPredicate_keysToFetch_error_(pred, fetch_keys, None) if not people: print 'No person found with the name "%s"' % (CONTACT_NAME,) return p = people[0] has_image = p.imageDataAvailable() if has_image: # Show the existing picture of the contact: img_data = p.imageData() img_data_str = string_at(img_data.bytes(), img_data.length()) img = ui.Image.from_data(img_data_str) img.show() # Pick a new image from photos: new_img_data = photos.pick_image(raw_data=True) if new_img_data: # Note: objc_util automatically converts bytearray to NSData new_img_bytes = bytearray(new_img_data) # Create a mutable copy of the fetched contact... mutable_contact = p.mutableCopy().autorelease() # Assign new image data... mutable_contact.imageData = new_img_bytes # Create a save request for he contact, and execute it... save_req = CNSaveRequest.new().autorelease() save_req.updateContact_(mutable_contact) store.executeSaveRequest_error_(save_req, None) if __name__ == '__main__': main()
-
Thank you @omz, the code you shared is working perfectly