Saving properties

I am working with Contacts.app and need to save changes made to a card (Person). In particular, if I have a record containing all the properties of an address and edit one or more of those property values (not the id though), how can I then save that record and so update the information of that card?

Is there a way to save the entire record in one go, rather than having to iterate through each property in the record and save its value individually?

Hi.

Yeah. In Contacts, save saves all changes to anything. Simply use it when you’ve finished.

tell application "Contacts"
	
	-- Do any required edits.
	
	save
end tell

Ok, indeed after updating I have to Save, but how do I ‘update’ all the properties of that address in one step rather than setting each property individually. The stored properties exist as a record and I have the modified properties as an identically structured record (I edited a copy of the original). Is there a way to simply set ALL properties to their new values (from the modified record) in one command? Or do I have to iterate through the entire record and set each property to the new value from the modified record.

Since I don’t necessarily know the structure of the record (it may be different classes I’m updating, like Phones etc) and so I don’t want to hard code each property update. I hoped there was a way to simply write the entire record in one step.

I’m beginning to think not.

So in the end I am iterating through the record and setting each property to the new value and then using save. But…

Contacts.app, does not show the changes. There doesn’t seem to be a ‘re-load’ option, but I browsed through several other Groups and Cards and then back to the one with which I’m testing. But it’s still showing the old data.

One might assume that my code to set the new values is flawed, but if I run the script again, the list I get back (I’m working with eMails) DOES show the updated values, perfectly as I set them and this is getting them all from Contact.app again so it obviously does have the new values.

If I Quit and restart Contacts.app and then run my script again, the list now supplied by Contacts.app is as it was in the first place. So the changes I made have been thrown away.

There is obviously a copy of the data (in memory I suspect) that Contacts.app supplies when requested by the script and which gets updated by the script, but so far I’ve been unable to get Contacts.app to actually save that to its permanent storage.

Any ideas?

Hi.

Although it’s not mentioned in Contacts’s dictionary, it seems that Contacts entries support the setting of a ‘properties’ property to a record containing the new data for all their properties which need to be changed:

tell application "Contacts"
	set thisPerson to first person whose selected is true -- CAUTION. THIS IS THE PERSON CURRENTLY DISPLAYED IN CONTACTS. MAKE SURE ITS NOT A CONTACT YOU WANT TO KEEP!
	-- Change some of the person's properties.
	set properties of thisPerson to {title:"Mr", first name:"Fred", last name:"Bloggs", birth date:(current date), department:"Chaos Distribution", job title:"Head of Scripting", note:"Just made this one up.  :)"}
	-- Change the properties of one of their phones.
	set properties of thisPerson's first phone to {label:"home", value:"0800 123 4567"}
	
	-- Save all the changes made.
	save
end tell

You can’t change a person’s ‘name’ or ‘vcard’. These are updated automatically from changes made to the other properties — such as ‘first name’ and ‘last name’. The properties of a person’s elements — such as their ‘addresses’ and ‘phones’ — have to be handled on a per-element basis.

‘save’ (no parameters) updates the display in Contacts immediately on my machines.

Well in truth, I’m doing this from JavaScript, but if I know how to do it in AppleScript, I can figure out how to make it work in JavaScript - in theory. :slight_smile:

Interesting to see properties being used in this way for bulk updating. I assume it updates the properties that are supplied in the command and doesn’t touch the other ones which is exactly what I wanted.

However I can tidy that up later. The problem first is that it’s not actually ‘saving’ the changes, yet it cannot be my method as if I run the same code to retrieve the emails again from that same person, I get back the list as per the changes I just made, even though that is not what is displayed in Contacts.app (and not what is supplied if I first Quit and restart the app). So Contacts.app has in some way been updated, just that the ‘in memory’ data has not been, well, saved - despite issuing a save command.

Just to be clear, I start by setting:-

Contacts = Application(‘Contacts’)

and then at the end of updating:-

Contacts.save

which as far as I can tell is the same as in AppleScript:-

tell application "Contacts" to save

but the new data is not ‘saved’ and remains in the memory/cache from where it will be taken the next time the commands to get that persons emails are run.

Is there perhaps a problem with ‘save’ in JavaScript? I could put this into an AS library and call that, but it should work in JS. I’m not getting any error.

Doesn’t appear to be a problem with ‘save’. I put that in an AS library and called that, but still the same problem.

So it’s as if I’m writing the updates to the wrong place, but that is not supported by the fact that when asking Contacts.app for those emails again, it sends them back with those updates.

So to say I’m puzzled is an understatement.:confused:

My JXA’s a bit … ah … rusty, but shouldn’t that be:

Contacts.save() ?

Ah could be. There doesn’t seem to be any complete documentation on JXA. You just have to ‘suck it and see’. What? Poor documentation from Apple? That can’t be, I hear you say. :smiley:

I’ll try it with the brackets, but I’m not hopeful as even running an AS save command didn’t actually work.

Well I’ll be…

That did the trick. I should have tried that, but hey, it’s my birthday and I’m not really concentrating. :slight_smile:

Odd though as calling an AS function to do the save didn’t work. I guess I won’t worry about that.

Anyway, thanks for pointing out what should have been obvious to me.

Happy birthday! :slight_smile: