omz:forum

    • Register
    • Login
    • Search
    • Recent
    • Popular

    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 invoking a block

    Pythonista
    3
    7
    2904
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • mikael
      mikael last edited by

      I am trying to implement a Pythonista API for WKWebView. All credit for all ObjC code so far goes to @mithrendal.

      For the load policy decision, I would need to invoke the decision handler with a single integer parameter. Repurposing @JonB code from the multipeer project I arrived at the following, but get an exception stating that the handler was never called.

      Any ideas? Thanks.

      class _block_descriptor (Structure):
        _fields_ = [('reserved', c_ulong), ('size', c_ulong), ('copy_helper', c_void_p), ('dispose_helper', c_void_p), ('signature', c_char_p)]
      InvokeFuncType = ctypes.CFUNCTYPE(None, *[c_void_p, ctypes.c_int])
      class _block_literal(Structure):
        _fields_ = [('isa', c_void_p), ('flags', c_int), ('reserved', c_int), ('invoke', InvokeFuncType), ('descriptor', _block_descriptor)]
        
      def webView_decidePolicyForNavigationAction_decisionHandler_(_self, _cmd, _webview, _navigation_action, _decision_handler):
        decision_handler = ObjCInstance(_decision_handler)
        retain_global(decision_handler)
        blk = _block_literal.from_address(_decision_handler)
        blk.invoke(decision_handler, 1)
      
      1 Reply Last reply Reply Quote 0
      • dgelessus
        dgelessus last edited by dgelessus

        IIRC block invoke functions take the block itself as an implicit first argument (basically like self). So you probably need to add an extra c_void_p in your InvokeFuncType's argument list, and add blk as the first argument in your blk.invoke call. Nevermind, decision_handler and blk both refer to the block.

        1 Reply Last reply Reply Quote 0
        • JonB
          JonB last edited by

          This post is deleted!
          1 Reply Last reply Reply Quote 0
          • JonB
            JonB last edited by

            are you sure your callback is getting called? maybe an logging line to check. objc_util has trouble parsing type encodings for things like blocks, or complicated structures, so the protocol type encoding is probably getting munged, in which case, your method might not be getting created correctly.

            Your block looks mostly okay -- you have the secret blk parameter, and the integer, though you might try c_void_p instead of None for restype.. i feel like i had to do that recently and couldnt explain why. You might also try c_long instead of c_int, as WKNavigationActionPolicy is defines as NSInteger, which an alias for c_long. if you run on 64 bit, there is a difference, though on 32 bit they are the same.

            1 Reply Last reply Reply Quote 0
            • mikael
              mikael last edited by

              Looks like the callback is indeed not getting called, and that is likely because I missed the bit below. I am having a hard time finding the documentation about how these should be changed — I tried *3, and then also removing one @, but no luck.

              f = webView_decidePolicyForNavigationAction_decisionHandler_
              f.argtypes = [c_void_p]*4
              f.restype = None
              f.encoding = b'v@:@@@@?'
              
              1 Reply Last reply Reply Quote 0
              • JonB
                JonB last edited by

                the runction prototype (just searvh for method name in google, and choose the apple docs) is:

                - (void)webView:(WKWebView *)webView 
                decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction 
                decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler;
                

                so, we have return type void, argtypes are 3 pointers, the last of which is a block. However, you also have the hidden self and selector args.

                So encoding would be b'v@:@@@?'
                argtypes would then be [c_void_p]*6 (though maybe 4.. i forget if the hidden args get added during the call.
                Im not 100% sure about the last @?, you might try plain @.

                mikael 1 Reply Last reply Reply Quote 0
                • mikael
                  mikael @JonB last edited by

                  @JonB, thanks. Turns out my earlier attempt actually worked, but I did not notice it because of another error in the code.

                  So, to conclude, these were the right values, and the policy decision is working as expected:

                  f = webView_decidePolicyForNavigationAction_decisionHandler_
                  f.argtypes = [c_void_p]*3
                  f.restype = None
                  f.encoding = b'v@:@@@?'
                  

                  I also got to learn about the crazy fun argtype encoding values Apple uses.

                  1 Reply Last reply Reply Quote 0
                  • First post
                    Last post
                  Powered by NodeBB Forums | Contributors