omz:forum

    • Register
    • Login
    • Search
    • Recent
    • Popular

    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 API - Group Modification

    Pythonista
    5
    31
    9477
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • JonB
      JonB last edited by

      You should take a look at the CNMutableContact created here, and you may be able to figure it out.

      There should be an attributes dates, which according to the objc docs is an array of CNLabeledValue objects, where the value is an NSDate.

      You can create NSDate using

      dateobj=ObjCClass('NSDate').dateWithTimeIntervalSince1970_(time.mktime(time.strptime('2017-06-18', '%Y-%m-%d')))
      
      CNLabeledValue=ObjCClass('CNLabeledValue')
      value=CNLabeledValue.alloc().init()
      value.label='birthday'
      value.value=dateobj
      
      Then you ought to be able to use
      
      CNMutableContact.dates=[value]
      
      
      cvp 1 Reply Last reply Reply Quote 0
      • cvp
        cvp last edited by

        As I didn't know which field you want to set, I let a print(dir(CNMutableContact)) in my script, so you could find your-self the name of the field..
        But now, as @JonB did the job, all is good so

        1 Reply Last reply Reply Quote 0
        • cvp
          cvp @JonB last edited by cvp

          @JonB CNLabeledValue has to be initialized differently

          	CNLabeledValue=ObjCClass('CNLabeledValue')
          	value=CNLabeledValue.alloc()
          	value.initWithLabel_value_('birthday',dateobj)
          

          But date has to be a NSDateComponents

          The app was terminated due to an Objective-C exception. Details below:
          
          2021-02-02 23:04:50.219269
          Labeled value <CNLabeledValue: 0x283090580: identifier=87E927A0-ED12-4AC9-89A8-EE6CCC75441D, label=birthday, value=2017-06-17 22:00:00 +0000, iOSLegacyIdentifier=-1> value 2017-06-17 22:00:00 +0000 has incorrect type __NSTaggedDate. It should be NSDateComponents.
          
          1 Reply Last reply Reply Quote 1
          • cvp
            cvp last edited by

            That works

            	dateComponents = ObjCClass('NSDateComponents').alloc().init()
            	dateComponents.day = 4
            	dateComponents.month = 5
            	dateComponents.year = 2017
            
            	CNLabeledValue=ObjCClass('CNLabeledValue')
            	value=CNLabeledValue.alloc()
            	value.initWithLabel_value_('birthday',dateComponents)
            	print(dir(CNLabeledValue))
            	CNMutableContact.dates=[value]
            
            osamu 1 Reply Last reply Reply Quote 1
            • osamu
              osamu @cvp last edited by

              @cvp @JonB
              Thank you folks.
              I'm just a Python beginner and I had no place to begin w/ Objective C stuff. Now I think I can begin to try.

              1 Reply Last reply Reply Quote 0
              • osamu
                osamu last edited by

                Now I’m trying to modify and save ‘dates’ field of an existing contact. Though the following script doesn’t spit errors but nothing happens to the contact. Could anybody help?

                from objc_util import *
                
                # ObjectiveC contacts
                CNContactStore = ObjCClass('CNContactStore').alloc().init()
                CNContact = ObjCClass('CNContact')
                Containers = CNContactStore.containersMatchingPredicate_error_(None,None)
                for Container in Containers:
                	id = Container.identifier()
                	predicate = CNContact.predicateForContactsInContainerWithIdentifier_(id)
                	# keys not exactly like in Apple doc
                	predicate_contacts = CNContactStore.unifiedContactsMatchingPredicate_keysToFetch_error_(predicate, ['familyName', 'givenName', 'middleName', 'dates'], None)
                	'''
                	print('First name: ', end='')
                	first_name = input()
                	print('Last name: ', end='')
                	last_name = input()
                	'''
                	first_name = 'Ludwig'
                	last_name = 'Beethoven'
                	for contact in predicate_contacts:
                		if first_name == str(contact.givenName()) and last_name == str(contact.familyName()):
                			break
                	CNMutableContact = contact.mutableCopy()
                	dateComponents = ObjCClass('NSDateComponents').alloc().init()
                	label = 'passing'
                	dateComponents.day = 26
                	dateComponents.month = 3
                	dateComponents.year = 1827
                	'''
                	print('Label: ', end='')
                	label = input()
                	print(label.capitalize()+' year: ', end='')
                	dateComponents.year = int(input())
                	print(label.capitalize()+' month: ', end='')
                	dateComponents.month = int(input())
                	print(label.capitalize()+' day: ', end='')
                	dateComponents.day = int(input())
                	'''
                	CNLabeledValue=ObjCClass('CNLabeledValue')
                	value=CNLabeledValue.alloc()
                	value.initWithLabel_value_(label, dateComponents)
                	CNMutableContact.dates=[value]
                
                	CNSaveRequest = ObjCClass('CNSaveRequest').new().autorelease()
                	CNSaveRequest.updateContainer_(CNMutableContact)
                	CNContactStore.executeSaveRequest_error_(CNSaveRequest, None) ```
                cvp 1 Reply Last reply Reply Quote 0
                • cvp
                  cvp @osamu last edited by

                  @osamu this works

                  # https://forum.omz-software.com/topic/2734/contacts-module-access-profile-picture/4
                  from objc_util import *
                  import photos
                  import time
                  	
                  # Load classes we need from Contacts.framework:
                  NSBundle.bundleWithPath_('/System/Library/Frameworks/Contacts.framework').load()
                  
                  def main():
                  	CNContactStore = ObjCClass('CNContactStore').alloc().init().autorelease()
                  	
                  	Containers = CNContactStore.containersMatchingPredicate_error_(None,None)
                  	for Container in Containers:
                  		containerId = Container.identifier()
                  		break						# get first container
                  		
                  	all_assets =photos.get_assets()
                  	asset = photos.pick_asset(assets=all_assets)
                  	img_data_bytes = asset.get_image_data().getvalue()
                  	
                  	CNMutableContact = ObjCClass('CNMutableContact').alloc().init()
                  	CNMutableContact.firstName = 'aaTest'	# just to be the first
                  	CNMutableContact.imageData = img_data_bytes
                  	#CNMutableContact.phoneNumbers = ['123','456']
                  	#print(dir(CNMutableContact))
                  	#return
                  		
                  	dateComponents = ObjCClass('NSDateComponents').alloc().init()
                  	dateComponents.day = 4
                  	dateComponents.month = 5
                  	dateComponents.year = 2017
                  
                  	CNLabeledValue=ObjCClass('CNLabeledValue')
                  	value=CNLabeledValue.alloc()
                  	value.initWithLabel_value_('passing',dateComponents)
                  	print(dir(CNLabeledValue))
                  	CNMutableContact.dates=[value]
                  	
                  	CNSaveRequest = ObjCClass('CNSaveRequest').new().autorelease()
                  	CNSaveRequest.addContact_toContainerWithIdentifier_(CNMutableContact, containerId)
                  	CNContactStore.executeSaveRequest_error_(CNSaveRequest, None)
                  
                  if __name__ == '__main__':
                  	main()
                  

                  1 Reply Last reply Reply Quote 1
                  • osamu
                    osamu last edited by

                    Wrong: CNSaveRequest.updateContainer_(CNMutableContact)
                    Correct: CNSaveRequest.updateContact(CNMutableContact)

                    Console:
                    First name: Ludwig
                    Last name: Beethoven
                    Label: passing
                    Passing year: 1827
                    Passing month: 3
                    Passing day: 26

                    Final code:

                    from objc_util import *
                    
                    # ObjectiveC contacts
                    CNContactStore = ObjCClass('CNContactStore').alloc().init()
                    CNContact = ObjCClass('CNContact')
                    Containers = CNContactStore.containersMatchingPredicate_error_(None,None)
                    for Container in Containers:
                    	id = Container.identifier()
                    	predicate = CNContact.predicateForContactsInContainerWithIdentifier_(id)
                    	# keys not exactly like in Apple doc
                    	predicate_contacts = CNContactStore.unifiedContactsMatchingPredicate_keysToFetch_error_(predicate, ['familyName', 'givenName', 'middleName', 'dates'], None)
                    	print('First name: ', end='')
                    	first_name = input()
                    	print('Last name: ', end='')
                    	last_name = input()
                    	for contact in predicate_contacts:
                    		if first_name == str(contact.givenName()) and last_name == str(contact.familyName()):
                    			break
                    
                    CNMutableContact = contact.mutableCopy()
                    dateComponents = ObjCClass('NSDateComponents').alloc().init()
                    print('Label: ', end='')
                    label = input()
                    print(label.capitalize()+' year: ', end='')
                    dateComponents.year = int(input())
                    print(label.capitalize()+' month: ', end='')
                    dateComponents.month = int(input())
                    print(label.capitalize()+' day: ', end='')
                    dateComponents.day = int(input())
                    CNLabeledValue=ObjCClass('CNLabeledValue')
                    value=CNLabeledValue.alloc()
                    value.initWithLabel_value_(label, dateComponents)
                    CNMutableContact.dates=[value]
                    CNSaveRequest = ObjCClass('CNSaveRequest').new().autorelease()
                    CNSaveRequest.updateContact(CNMutableContact)
                    CNContactStore.executeSaveRequest_error_(CNSaveRequest, None)
                    

                    I couldn’t attach the capture 😣

                    cvp 2 Replies Last reply Reply Quote 0
                    • cvp
                      cvp @osamu last edited by

                      @osamu you can also see this

                      # add a date field with custom label to an existing contact
                      #   of course extensible to all fields
                      from objc_util import *
                      	
                      def main():
                      	
                      	CNContactStore = ObjCClass('CNContactStore').alloc().init().autorelease()
                      
                      	# get a particular contact	
                      	contact_name = 'aaTest'
                      	date_label   = 'my own label'
                      	date_ymd     = '20200201'
                      	CNContact = ObjCClass('CNContact')	
                      	predicate = CNContact.predicateForContactsMatchingName_(contact_name)
                      	predicate_contacts = CNContactStore.unifiedContactsMatchingPredicate_keysToFetch_error_(predicate, ['dates'], None)
                      	
                      	for contact in predicate_contacts:
                      		# Create a CNMutableContact by copy of an existing contact
                      		CNMutableContact = ObjCClass('CNMutableContact').alloc().init()
                      		CNMutableContact = contact.mutableCopy()
                      
                      		# Create a date 		
                      		NSDateComponents = ObjCClass('NSDateComponents').alloc().init()
                      		NSDateComponents.setDay_  (int(date_ymd[6:8]))
                      		NSDateComponents.setMonth_(int(date_ymd[4:6]))
                      		NSDateComponents.setYear_ (int(date_ymd[0:4]))
                      
                      		# create a custom label
                      		CNLabeledValue = ObjCClass('CNLabeledValue').alloc()
                      		CNLabeledValue.initWithLabel_value_(date_label, NSDateComponents)
                      
                      		# create a date with custom label		
                      		CNMutableContact.setDates_(ns([CNLabeledValue]))
                      
                      		# save modified contact		
                      		CNSaveRequest = ObjCClass('CNSaveRequest').new().autorelease()
                      		CNSaveRequest.updateContact_(CNMutableContact)
                      		CNContactStore.executeSaveRequest_error_(CNSaveRequest, None)
                      
                      if __name__ == '__main__':
                      	main()
                      
                      1 Reply Last reply Reply Quote 0
                      • osamu
                        osamu last edited by

                        Got it. For loop was no use.

                        cvp 1 Reply Last reply Reply Quote 0
                        • cvp
                          cvp @osamu last edited by

                          @osamu 👍

                          1 Reply Last reply Reply Quote 0
                          • cvp
                            cvp @osamu last edited by

                            @osamu said:

                            I couldn’t attach the capture 😣

                            See here

                            1 Reply Last reply Reply Quote 0
                            • osamu
                              osamu last edited by osamu

                              Thanks ❣️🙏
                              Beethoven

                              cvp 1 Reply Last reply Reply Quote 0
                              • cvp
                                cvp @osamu last edited by

                                @osamu do you have his phone number ? 😂

                                1 Reply Last reply Reply Quote 0
                                • osamu
                                  osamu last edited by

                                  Well, call him up and ask him to write Symphony No.10? 😂

                                  1 Reply Last reply Reply Quote 0
                                  • First post
                                    Last post
                                  Powered by NodeBB Forums | Contributors