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.
Problems when using objc_util()
-
@cvp
jonb said :
the Pythonista hava two threads
1.The main thread, or ui thread
2.The interpreter threadI don't know if the error is related to IOS thread.
but I remember that the apple development document said that the NSItemProvider interface should be used in DispatchQueue.main.async { }I'm learning something about it..
-
@rozaimech what is strange is that itemProvider.loadObjectOfClass_completionHandler_ has a
__call__
method, thus should be callable
-
The code works, the problem is that on_main_thread function (see objc_util source code) raises an error if the called function is not Python-callable, but on_main_thread function continues and the function is called anyway...
-
on_main_thread(itemProvider.loadObjectOfClass_completionHandler_(ObjCClass('UIImage'),handler_block))
Try instead:
on_main_thread(itemProvider.loadObjectOfClass_completionHandler_)(ObjCClass('UIImage'),handler_block)
In other words, on_main_thread returns a method, which you call using arguments. The way you had it, you were calling a function, and passing it's output, which was not a function, to on_main_thread.
on_main_thread(original_func)(args)
I would also question whether you need to be calling on_main_thread at all here.
-
@JonB said:
on_main_thread(itemProvider.loadObjectOfClass_completionHandler_)(ObjCClass('UIImage'),handler_block)
Works 😀
No other words than magic
-
Ahh, I see you are trying to make sure the callback gets run on the main thread... The above code doesn't do that--it just sets the callback on the main thread.
If things within the callback must be done on the main thread, you need such code inside the callback handler itself. For instance, you could use a decorator on the handler.
Another common problem is calling ObjCInstance on some non object. @shinyformica had a thread a while back about a wierd seg fault, that we were able to fix I think by prechecking some condition in a loop, and only proceeding once things were correct. The details evade me.
-
@JonB Without on_main_thread, segmentation fault
-
@JonB this also gives segmentation fault
@on_main_thread def handler(_cmd,obj_ptr):
-
@cvp said:
on_main_thread(itemProvider.loadObjectOfClass_completionHandler_)(ObjCClass('UIImage'),handler_block)
works once and crashes with segmentation fault the second time...
-
-
@cvp
ok...we won# coding: utf-8 from objc_util import * import ui,time def dropInteraction_canHandleSession_(_m,_c,interaction,session): return True def dropInteraction_sessionDidUpdate_(_m,_c,interaction,session): return ObjCClass('UIDropProposal').alloc().initWithDropOperation(2).ptr def dropInteraction_performDrop_(_m,_c,interaction,session): session=ObjCInstance(session) def handler(_cmd,obj_ptr): obj=ObjCInstance(obj_ptr) print(obj) handler_block = ObjCBlock(handler, restype=None, argtypes=[c_void_p,c_void_p]) def ptimer(progress): while True: if(progress.totalUnitCount()==progress.completedUnitCount()): break time.sleep(0.1) for item in session.items(): itemProvider =item.itemProvider() uiimage =ObjCClass('UIImage') if(itemProvider.canLoadObjectOfClass(uiimage)): progress=itemProvider.loadObjectOfClass_completionHandler_(ObjCClass('UIImage'),handler_block) ptimer(progress) elif(itemProvider.canLoadObjectOfClass(NSString)): progress=itemProvider.loadObjectOfClass_completionHandler_(NSString,handler_block) ptimer(progress) else: print(itemProvider) methods=[dropInteraction_canHandleSession_,dropInteraction_sessionDidUpdate_,dropInteraction_performDrop_] protocols=['UIDropInteractionDelegate'] dropDelegate=create_objc_class('MydropDelegate',methods=methods,protocols=protocols) Delegate=dropDelegate.alloc().init() dropInteraction=ObjCClass('UIDropInteraction').alloc().initWithDelegate(Delegate) drop_view = ui.View(bg_color='blue') drop_view.objc_instance.setUserInteractionEnabled(True) drop_view.objc_instance.addInteraction(dropInteraction) drop_view.present()
-
-
@rozaimech, congratulations!
So I take it this no longer crashes? Can you say what was the key difference – one less handler argument, the progress tracker, or something else I am not seeing?
-
@mikael said:
one less handler argument,
I think that third argument of handler, being an error parameter, could/should be there in case of error and you want to know the reason, but anyway, it runs ok so
-
@mikael I think that the reason is that without progress tracker, we analyzed too early the object parameter in the handler, so sometimes the object was ready, other times it was not thus crash
-
@cvp, thanks. That sounds likely, due to the ObjCInstance wrapper not always being up to speed with the actual ObjC instance.
-
@mikael Sincerely, I don't know but why to define a "completion handler" (which we could think it is called after completion) and also a "progress tracker"?
-
@cvp
This is Apple's UI design. The completion handler is asynchronous and runs immediately.
"ItemProvider. Loadobjectofclass_completionhandler_()" returns a progress, which can cancel operations or obtain progress data. During this period, developers can design a set of suitable UI animation to reduce the waiting experience of users, or cancel loading. -
@rozaimech Yes, I know, I had read it also but, I think (maybe, or better, sure, I'm wrong) that a "completion handler" is called after completion...
-
@cvp
Usually the second run has an error,maybe it's after first completion......