ObjC Event Methods

I’m porting some OS X classes. In ObjC it is very common for classes to have Methods that are called by the Cocoa framework indicating something has happened natively to the class or via a declared protocol, which in Xojo is termed an Event. How can I “hook up” this Method - Event to my class via declares?

In Xcode I would just write the method signature and it would be called.

Thank you.

What classes are you looking to deal with? I do this with dynamically created classes to which Xojo methods can be added as the implementation (figured out from investigating macoslib). I don’t know if there’s a way to add methods to pre-existing classes or instances. Anyways, an important point is that the Xojo method used must be Shared. This is because the callback includes an instance pointer as the first parameter which Xojo doesn’t know how to handle. So if you need the method to trigger on an instance the Shared method will need to dispatch the call to the appropriate instance.

This is plucked from a Canvas subclass that adds the magnifyWithEvent event. First an NSView subclass is dynamically created to which the Xojo Shared method is added as the implementation of magnifyWithEvent. Then an instance of this subclass is created and set as a subview of the Canvas, and the Canvas itself added to the dispatch list.

Shared GesturePane As Ptr //pointer to NSView subclass
Shared dispatchList() As MyGesturingCanvas //array of Canvas instances (could be a dictionary)
subviewid As Ptr //pointer to this Canvases GesturePane instance

soft declare function NSSelectorFromString lib CocoaLib (aSelectorName as CFStringRef) as Ptr
soft declare function objc_allocateClassPair lib CocoaLib (superclass as Ptr, name as CString, extraBytes as Integer) as Ptr
soft declare sub objc_registerClassPair lib CocoaLib (cls as Ptr)
soft declare function NSClassFromString lib CocoaLib (aClassName as CFStringRef) as Ptr
soft declare function class_addMethod lib CocoaLib (cls as Ptr, name as Ptr, imp as Ptr, types as CString) as Boolean

if GesturePane = nil then //need to create subclass

  //dynamically create NSView subclass GesturPane
  GesturePane = objc_allocateClassPair(NSClassFromString("NSView"), "GesturePane", 0)
  objc_registerClassPair(GesturePane)   //must register GesturePane to be used

  //add Xojo Shared method impl_Gesture to GesturePane as the implementation of magnifyWithEvent
  if not class_addMethod(GesturePane, NSSelectorFromString("magnifyWithEvent:"), AddressOf impl_Gesture, "v@:@") then break


soft declare function alloc                  lib CocoaLib selector "alloc" (classRef as Ptr) as Ptr
soft declare function initWithFrame          lib CocoaLib selector "initWithFrame:" (obj_id as Ptr, frameRect as NSRect) as Ptr
self.subviewid = initWithFrame(alloc(GesturePane), frame)   //allocate an instance of GesturePane and store the pointer in subviewid
addSubview(Ptr(self.Handle), self.subviewid)                //link instance as subview of this RB Canvas
dispatchList.Append self                                    //add self to dispatch list

//Now when the event occurs it calls this method…
Private Shared Sub impl_Gesture(pid as Ptr, sel as Ptr, evt as Ptr)
//Find the Canvas with matching responder and send it the event
for i As integer = 0 to dispatchList.Ubound
if dispatchList(i).subviewid = pid then
End Sub

//…which sends it to an instance method where a true Xojo event can be raised
Private Sub sendMagnify(evt As Ptr)
//extract evt info
RaiseEvent GestureMagnify(magnification(evt), pnt.x, pnt.y)
End Sub[/code]

Here’s a link to the dynamic creating functions ObjCRuntimeRef

Also note the first 2 parameters of impl_Gesture. These get added to match what the OS is calling. Like in Xojo instance methods the first is a pointer to the instance being called (and used for lookup) while the second is a selector thingy.

Thanks for your reply Doofus, I will look this through.