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.
Objc_utils and EventKit
-
I finally took a look at objc_utils today. I didn't know where to begin so I found an example which I thought would be useful for me on the apple developer site using EventKit.
Here is the example site and I'm looking at the example of retrieving events from the EKEventStore using a predicate.
I have no clue what is going on. Here's what I have so far. I know there are problems, but I don't know why. I am also not sure if I have the syntax correct.
If anyone could help with this I would appreciate some suggestions and even explanations of how to use objc_util. I've read through the documentation a bit, but I'm afraid it's a little bit over my head.
If I'm able to have a list of events from my calendar to manipulate in Pythonista it is quite practical...
Thanks everyone!
from objc_util import * store = ObjCClass('EKEventStore').alloc().init() #store._requestAccessForEntityType_() #there needs to be permission granted to access the calendar, not sure exactly how to implement that. cal = ObjCClass('NSCalendar').currentCalendar() oneDayAgoComponents = ObjCClass('NSDateComponents').alloc().init() oneDayAgoComponents.day = -1 date = ObjCClass('NSDate') oneDayAgo = cal.dateByAddingComponents_toDate_options_(oneDayAgoComponents, date, 0) #oneDayAge is None?? oneYearFromNowComponents = ObjCClass('NSDateComponents').alloc().init() oneYearFromNowComponents.year = 1 oneYearFromNow = cal.dateByAddingComponents_toDate_options_(oneDayAgoComponents, date, 0) #oneYearFromNow is None?? #predicate = store.predicateForEventsWithStartDate_endDate_calendars_(oneDayAgo, oneYearFromNow, None) #this predicate line ^^ crashes pythonista
-
I'll get into the permission dialog and predicate construction a bit later, but there are some simple errors in your date calculation logic that are quite easy to fix.
First off, your
date
variable refers to theNSDate
class, not a specific instance, so adding components to it etc. makes no sense and fails silently (I'm actually surprised that it doesn't crash). Just usedate = ObjCClass('NSDate').date()
to get an instance that refers to the current date/time.oneDayAgo
andoneYearFromNow
shouldn't beNone
anymore now, but you'll notice that you have a copy/paste bug in the calculation ofoneYearFromNow
– you passoneDayAgoComponents
to thedateByAddingComponents...
method, but it should obviously beoneYearFromNowComponents
. -
@omz thanks so much.
As you've said I have fixed those simple errors and now I have my date components okay.Looking forward to more answers about the access, predicate, and array. I failed to mention the NSArray - but it is on the website. I didn't try to code that after I got really stuck with the predicate.
-
Here's how you can show the calendar access permission dialog – this is required for most EventKit methods to return anything useful, so this should be the first thing you do. Note that the dialog will only be shown once – if you deny access, you can still enable it in the Settings app, but you won't be asked again in Pythonista.
store = ObjCClass('EKEventStore').alloc().init() access_granted = threading.Event() def completion(_self, granted, _error): access_granted.set() completion_block = ObjCBlock(completion, argtypes=[c_void_p, c_bool, c_void_p]) store.requestAccessToEntityType_completion_(0, completion_block) access_granted.wait()
(I'm just ignoring the possibility that access was denied here for simplicity, you might want to show an error message in that case or whatever.)
By the way, if you've granted access once, it's no longer necessary to run the code above (but you may want to leave it in there in case you want to run it on another device),
-
It looks like the crash you were seeing with the predicate was because you passed
None
as start and end date. It doesn't crash for me now, and fetching events that match the predicate works:# ... predicate = store.predicateForEventsWithStartDate_endDate_calendars_(oneDayAgo, oneYearFromNow, None) events = store.eventsMatchingPredicate_(predicate) print events
-
@omz thanks again!
Got it working now....had to also import threading
Great!