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 in contacts module
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 in contacts 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 the contacts module. You can't get at the pointers to the underlying data structures in contacts, so if you want to edit a profile picture of a person using objc_util, you also have to find the right person object using that, and can't use the simpler contacts 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:
ui.Image to show it in the consoleBefore 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