On 6 Mar 2015, at 3:37 pm, Alex Hall <email@hidden> wrote:
First, the length() property always gives me an error. I've tried it with and without the parentheses, but it fails either way.
My bad. That should be |count|(). Too much AppleScript muscle memory...
Next, I did get the script to run. I switched to a different calendar name, and suddenly got an upcoming event. Best of all, the event is a repeating one set a long time ago, so I know that part is working perfectly!
Good. The problem is, as I try to modify your example so I can iterate over all the events returned, I can't access the properties of any of them. Here's the snippet, which is in place of your lines joining all the titles:
set theEvents to (theEKEventStore's eventsMatchingPredicate:thePred)
repeat with e in theEvents display dialog (e's valueForKey:"title") & ". Starts on " & (e's valueForKey:"startDate") end repeat
The script log is empty, and the error just says: Can’t make «class ocid» id «data optr000000000038C30080600000» into type list, record or text.
You have to get used to the fact that, apart from some numbers, Cocoa methods return Cocoa objects, and to do AppleScript things to them, you need to coerce them to their AppleScript equivalents.
So you need "set theEvents to (...) as list" before you can iterate through it like an AS list.
Using "repeat with e in theEvents" works fine, but you're better off using "repeat with i from 1 to count of...". The problem with using "repeat with" is that there's a bug that is triggered by trying to convert an object reference to a Cocoa object to a source string. You don't do that in scripts, but editors can and do when you're writing them, so it's best to avoid the problem.
Then when you get to the display dialog bit, you have to coerce again. You also don't need to use valueForKey: -- that's just a quick way of calling a method on all the items in an array, and you no longer have an array. And Cocoa dates don't coerce, so you the simplest thing is to get the description property, which returns a string. So something like:
display dialog ((e's title()) as text) & ". Starts on " & (e's startDate()'s |description|()) as text
Or perhaps better:
display dialog (current application's NSString's stringWithFormat_("%@. Starts on %@", e's title(), e's startDate())) as text I suspect it doesn't like me iterating, meaning the NSArray isn't being given to AS in a way it understands. I'm guessing, though, and my hypothesis makes little sense. If AS and Cocoa can work together, data types would be transparent between them, right?
You might think so, but it's not that simple. If a method requires, say, an NSString for an argument, you can pass an AS string and it will be converted automagically. But if a method returns an NSString, you have to coerce it to use it as an AS string. This is a Good Thing. If that didn't happen, you wouldn't be able to call NSString instance methods on it (and unnecessary conversions would waste time and memory).
The other odd thing is that this suddenly started working today, once I re-checked my calendar titles (yeah, my mistake there--it helps to use calendars that, um, have upcoming events). I was never prompted to allow access to Calendars, though, or given any security warnings of any kind. I'd rather avoid distributing this as an app or applet if I could, but since I'm not being shown any security warnings, I can't say how using a script will go over on others' machines. I just can't figure out why I was never asked to grant access to Calendars.
I have a feeling Script Editor gets access by default. But I'm really unsure of that side of things.
|