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 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.
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.
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.
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.
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=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]
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 )
…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?