Obj-C Blocks as Callbacks

I posted a similar question with regard to a specific animation scenario, but I thought I’d post a more general question with a more descriptive subject in the hope that it would garner a bit more attention (and perhaps even a definitive answer from the powers that be at Xojo). So my question is…

Given the numerous places in Cocoa that use blocks as callbacks, is there a way to make use of them in Xojo? Can I somehow get a Xojo method to execute as a callback if it’s declared in the Cocoa framework as a block?

I have been unsuccessful so far, but perhaps I haven’t hit upon the magic recipe.

:-/

Thanks much,

-Steve

Well, I could provide a plugin to offer generic blocks as class with events.

Thanks for the reply, Christian. If you’re saying that one would be able to pass a reference to such a class to a Cocoa API call and that it would fire off an event when the callback was invoked, that would be pretty sweet. If you decide to pursue it, let me know.

-Steve

Hi Christian, is a plugin the only way or is it possible with declares?

I dont think you’ll be able to use a declare to create an Obj-C block

Well, if you have a use for that you should email me.
Maybe we have that functionality already in the plugins.
Or we can discuss ways on how to implement this.

I am not speaking or acting as a representative of Xojo, Inc. in this post. All statements, views, or content below are my own.

Here’s a plugin I wrote that will wrap any delegate in an Objective-C block and doesn’t use private APIs <Blocks Plugin >.

Usage:

  • To create a block from a Delegate, call ObjCBlocks.CreateBlock, passing in your Delegate object.
  • When done with the block, call ObjCBlocks.ReleaseBlock on the pointer you got back from CreateBlock. Failing to do so will create memory leaks.

Note that some APIs that take blocks will invoke them on non-main threads. Even though this plugin lets you create a block, it does not magically become safe to use these APIs. Crashes or other hilarity will ensue.

Awesome Joe !

Good, but we would certainly need more. Like allowing parameters on the block or run on main thread.
In the AVFoundation plugin I made earlier this year, I have dozens of block based events there. And that was sometimes a lot of work to have it work right.

Joe, you pass delegate target with AddressOf. How do you call a method in the plugin on there? You just get an object as far as I see.

I am not speaking or acting as a representative of Xojo, Inc. in this post. All statements, views, or content below are my own.

REALGetDelegateInvoker.

I am not speaking or acting as a representative of Xojo, Inc. in this post. All statements, views, or content below are my own.

Not sure what you mean by allowing parameters. The plugin takes any delegate and turns it into a block, regardless of whether or not it has parameters. The only thing is that, like declares and callbacks, the signatures have to match. Take a look at the demo.

Actually you can; I’ve done it. A plugin allows one to use delegates of object methods, saving a lot of hassle.

Wow, you rock, Joe! I can’t wait to try it!

-Steve

Wow, really? I’d sure be curious to know what kind of code gymnastics you had to perform to accomplish it.

:slight_smile:

-Steve

I am not speaking or acting as a representative of Xojo, Inc. in this post. All statements, views, or content below are my own.

Without seeing your code, I’m assuming you use objc_getClass or NSClassFromString to get the value to shove into the block’s isa member. I don’t think any of the actual runtime class names are specified as public API.

I would be very interesting to see you code. It’s available somewhere?

[quote=24739:@Joe Ranieri]I am not speaking or acting as a representative of Xojo, Inc. in this post. All statements, views, or content below are my own.

Without seeing your code, I’m assuming you use objc_getClass or NSClassFromString to get the value to shove into the block’s isa member. I don’t think any of the actual runtime class names are specified as public API.[/quote]

Correct.

It was just a test project. Support for blocks is really best done in a plugin, and it would be nice for it to be added to the xojo framework.

1 Like

Well Joe already gave the plugin out

So I tried this out, and it works great! It seems to be exactly what I was looking for. Thanks again, Joe.

I do have a question, however. When using a block as a callback invoked from asynchronously executed code, what’s the best way to handle releasing the block?

For instance, if I’m using a block as the completionHandler with NSAnimationContext as follows…

[code]Dim block as Ptr = ObjCBlocks.CreateBlock( AddressOf myMethod )

beginGrouping( animationContext )
setDuration( currentAnimationContext( animationContext ), 3.00 )
setCompletionHandler( currentAnimationContext( animationContext ), block)
setAlphaValue( animator(Self.Handle ), 0.3)
endGrouping( animationContext )

ObjCBlocks.ReleaseBlock( block )[/code]

…then the block would be released before the animation completes and thus before the block executes, which seems like a bad idea. Would it be acceptable to stash a pointer to the block in a property and then release the block from within the block code itself? What’s the best way to handle this in a way that’s not asking for trouble?

Thanks much,

-Steve