Objective-C Blocks! ( invoking)

Ok,
I’ve been pulling hair all day and I finally figured out how to invoke an Objective-C Block from Xojo.

I’ve seen callbacks passed from functions that can be cast to a delegate and invoked in Xojo, but today I needed to handle a “block”… A handler the WebKit framework hands you to call from webView:decidePolicyForNavigationAction:decisionHandler:

The Apple docs look like this…

- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler
I needed to call the “(void (^)(WKNavigationActionPolicy))decisionHandler” part as a delegate.
It didn’t look like something that could be done, as it’s not a “function” and so cannot be used to construct a Xojo delegate.

but…

declare function imp_implementationWithBlock lib "libobjc.dylib" (block as ptr) as ptr
This function takes a “block” as it’s argument, and returns a function. The function can then be used to construct a Xojo delegate and called with .invoke!

I thought I’d share!

You could have just used the Block Plugin :stuck_out_tongue:
https://forum.xojo.com/3586-obj-c-blocks-as-callbacks/0

I think he was trying to do the opposite of the plugin’s function, instead of creating a block to pass to a function he was trying to take a block passed from a function and invoke it. Not sure the plugin supports that?

Hmmm upon rereading Jims post you might be right

However this is the sort of thing Joe does like to tinker with in his “spare” time (such as it is for all of us at the moment)
Would seem a natural addition to the plugin

I’d ping him & see
At the very least he might be able to point out whether there are implications from invoking that obj-C method directly (ownership, retain/ release or lord knows what else) and how it all plays with the Xojo runtime

imp_implementationWithBlock is an expensive function that I’d avoid. It’s also going to result in your process accumulating memory each time it’s called.

What I’d do instead is create a structure:

Structure Block_layout isa_ As Ptr flags As Int32 reserved As Int32 invoke As Ptr descriptor As Ptr End Structure

create a delegate type that matches the block’s signature:

Delegate Sub NavDecisionHandler(obj As Ptr, policy As Integer)

and in your callback, you can do something like this:

[code]Sub DecidePolicyForNavigationAction(obj As Ptr, cmd as Ptr, webView As Ptr, navigationAction As Ptr, decisionHandler As Ptr)
Const WKNavigationActionPolicyAllow = 1

Dim fp As NavDecisionHandler = New NavDecisionHandler(decisionHandler.Block_layout.invoke)
fp.Invoke(decisionHandler, WKNavigationActionPolicyAllow)
End Sub[/code]

Ah, much better! I didn’t look at the actual structure of a Block. Very cool indeed!

and just for the archives, a couple of syntax adjustments. (added New and Invoke)

[code]
Sub DecidePolicyForNavigationAction(obj As Ptr, cmd as Ptr, webView As Ptr, navigationAction As Ptr, decisionHandler As Ptr)
Const WKNavigationActionPolicyAllow = 1

Dim fp As NavDecisionHandler = new NavDecisionHandler(decisionHandler.Block_layout.invoke)
fp.Invoke(decisionHandler, WKNavigationActionPolicyAllow)
End Sub[/code]

Also, the compiler won’t let you use “isa” as a member name in the struct.

Sorry, I wrote it quickly in the forum post box and didn’t actually test it.

Thanks for sharing your thoughts Jim and Joe for the XOJO plugin handling objC blocks.
Works like a charm.

Joe, I am aware that you are probably in need of a break after conquering the last compiler issues lately. So please don’t take this as an urgent request. But how are the chances for an 64bit-compatible blocks plugin? I’d like to alleviate the MacOSLib problems a bit by publishing Foundation & Core Foundation classes for OS X soon, but without a block option for OS X this would be a very limited selection. Thanks a lot!

(Or Jim: Did you find time to create a similar method to the blocks plugin?)

I’ve updated the plugin to support 64-bit builds.

Superb, thanks mate.

Thanks a lot, Joe!

I keep running into this thread when searching for threads related to HANDLING Block callbacks. Jim, would you please rename this thread to something more specific, such as “Invoking Objective-C blocks”?

Wow, that was quick. Thanks!