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.
KVO on WKWebView
-
I'm trying out Key-Value-Observing with WKWebView in objc_util.
class WebView(ui.View): def __init__(self): self.create_webview() @objc_util.on_main_thread def create_webview(self): self.webview = objc_util.ObjCClass("WKWebView").alloc().initWithFrame_(...) self.objc_instance.addSubview_(self.webview) class View(ui.View): def __init__(self): self.webview = WebView() self.add_subview(self.webview) observer = objc_util.create_objc_class("observer", methods=[self.observeValueForKeyPath_ofObject_change_context_]) self.webview.webview.addObserver_forKeyPath_options_context_(observer, "canGoBack", 0, None) self.webview.webview.addObserver_forKeyPath_options_context_(observer, "canGoForward", 0, None) ... def observeValueForKeyPath_ofObject_change_context_(_self, _cmd, _path, _obj, _change, _context): ...
I'm using something like this, but
observeValueForKeyPath_ofObject_change_context_
doesn't seem to get called. Is there something wrong? -
@vivek101 Thank you for your welcome and for answering my question.
I tried the solution you showed, but it still seems that
observeValueForKeyPath_ofObject_change_context_
is not called.
Also, when I specified a non-existent name inkeyPath
ofaddObserver
, nothing happened as well.I'm not familiar with Objective-C and there are many things I don't understand, but I have the following questions:
- I understand that in
create_objc_class
the superclass defaults toNSObject
. - When using
observeValueForKeyPath_ofObject_change_context_
as a class method, shouldn't I use theclassmethod
argument ofcreate_objc_class
?
- I understand that in
-
I also tried programs like:
class WebView(ui.View): def __init__(self): self.create_webview() @objc_util.on_main_thread def create_webview(self): self.webview = objc_util.ObjCClass("WKWebView").alloc().initWithFrame_(...) self.objc_instance.addSubview_(self.webview) class View(ui.View): def __init__(self): self.webview = WebView() self.add_subview(self.webview) observer_cls = objc_util.create_objc_class("observer_cls", methods=[self.observeValueForKeyPath_ofObject_change_context_]) observer = objc_util.ObjCClass("observer_cls").alloc() self.webview.webview.addObserver_forKeyPath_options_context_(observer, "canGoBack", 0, None) self.webview.webview.addObserver_forKeyPath_options_context_(observer, "canGoForward", 0, None) ... def observeValueForKeyPath_ofObject_change_context_(_self, _cmd, _path, _obj, _change, _context): ...
observer
is used as an instance ofobserver_cls
.
But in this case an error occurs. _objc_exception.py looks like this:Exception ignored on calling ctypes callback function: <bound method View.observeValueForKeyPath_ofObject_change_context_ of <__main__.View object at 0x116bbc180>> TypeError: View.observeValueForKeyPath_ofObject_change_context_() takes 6 positional arguments but 7 were given
-
-
@indoxan you were on the right track with your second try. But you need to use
(self, _obj, _cmd, ...)The python self gets eliminated, but the objc method needs to have two hidden arguments, _obj, _cmd. The error says that the system tried to call with 7 arguments, but your method (when converted to a function) only takes 6.
def observeValueForKeyPath_ofObject_change_context_(_self, _cmd, _path, _obj, _change, _context): Should be def observeValueForKeyPath_ofObject_change_context_(self, _self, _cmd, _path, _obj, _change, _context):
-
@indoxan another problem might be that you aren't creating an instance, you are creating a class in your original code. The second code called alloc but not init.
You should use create_ObjC_classs outside of the class, at the start of your script:
MyObserver = create_objc_class(...)
Then, inside init:
self.observer = MyObserver.alloc().init()
It is important that both your instance and class continue to exist in python after the scope ends, otherwise your object maybe garbage collected, which can cause crashes.
-
-
@indoxan 👍