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.
Help with blocks (again!)
-
Hey community,
I need you help for a little objcutil script.
I wanna use Core Spotlight to index some results in spotlight (iOS 9)
I set the attributes and the item correctly but i'm having trouble with indexing cause i don't know how to "convert" the normal objc block to objcutil correctly.I basically have this code for initializing it:
def handlr(_cmd,error): if error: print error handler= ObjCBlock(handlr,restype=None,argtypes=[c_void_p,c_void_p]) defindex = index.defaultSearchableIndex() defindex.indexSearchableItems_completionHandler_(item,handler)
But it crashes the app ( i assume my block doesn't respect some conditions)
The docs say this for the indexing an item:
- (void)indexSearchableItems:(NSArray<CSSearchableItem *> * _Nonnull)items completionHandler:(void (^ _Nullable)(NSError * _Nullable error))completionHandler
Is there something i'm missing?
Thanks in advance for your help
Filippo -
if you just use pass inside the handlr body, do you still crash?
what are you using for
item
... that looks like a tricky typedef to get right.. -
Have you tried just passing
None
as the completion handler? The block is declared as nullable, so that should work. I would suspect that the actual problem is somewhere else, haven't had time to try this myself yet. -
I've played around with the CoreSpotlight framework a little bit, and the code below doesn't crash... It adds an item to the default index, which then shows up in Spotlight's search results. Tapping on the search result starts Pythonista, but that's pretty much it — as far as I can see, there's no easy way for you to do anything in response to a search result being opened, unless I make some changes in the app itself.
from objc_util import * UUID = '1234abcd' TITLE = 'Pythonista Spotlight Test' TEXT = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla rhoncus rutrum ornare. Integer ac dolor.' CoreSpotlight = NSBundle.bundleWithPath_('/System/Library/Frameworks/CoreSpotlight.framework') CoreSpotlight.load() CSSearchableItem = ObjCClass('CSSearchableItem') CSSearchableIndex = ObjCClass('CSSearchableIndex') CSSearchableItemAttributeSet = ObjCClass('CSSearchableItemAttributeSet') idx = CSSearchableIndex.defaultSearchableIndex() attr_set = CSSearchableItemAttributeSet.alloc().initWithItemContentType_('public.text') attr_set.setTitle_(TITLE) attr_set.setContentDescription_(TEXT) item = CSSearchableItem.alloc().initWithUniqueIdentifier_domainIdentifier_attributeSet_(UUID, None, attr_set) def handler_func(_cmd, error): print 'Completion handler called' if error: print ObjCInstance(error) handler= ObjCBlock(handler_func, restype=None, argtypes=[c_void_p, c_void_p]) idx.indexSearchableItems_completionHandler_([item], handler) item.release() attr_set.release()
Your block looked fine btw, I haven't really changed that, so I suspect the crash came from somewhere else.
-
Thanks for the code.
So, the crash was due to the item not in an nsarray (i initially solved it without your code) but it wasnt actually indexing it.
The problem was this: instead of attr_set.setTitle("HelloWorld") i wrote attr_set.title = "HelloWorld" -.- i am so stupid. Thanks for your help, Solved :-) -
I wonder if it would be possible for
__getattr__
and__setattr__
to check for the existence of a selectorsomeproperty()
, and alsosetSomeproperty_(value)
, and if both exist, then treat calls tosomeobj.someProperty=somevalue
orsomeobj.someProperty
as a call to the appropriate selector. It might help fix problems like these, and makes ObjCClasses a little more pythonic. -
It would be definitely cool :-)
-
@JonB I've thought about that as well... I've actually already implemented
__setattr__
in this way for the next build, so thatsomeobj.someProperty = foo
is equivalent tosomeobj.setSomeProperty_(foo)
.The problem I see with
__getattr__
is that this would break existing code. Something likefoo = someobj.someProperty()
would fail because the property value wouldn't be callable... I'm generally okay with breaking code during the beta, but I need to think about this a little more than for__setattr__
(which still allows the old syntax).