The pb callbacks functions must match the method definition, the first two params are always self and cmd, then the rest, see example.
Inside the callback you have to call the original method by calling the new method because since they are switched you are calling the original one, it is a bit confusing but is how it works, see example.
The function only switches the method if the new method does not already exists.
Code: Select all
Procedure cocoa_swizzle_methods(class.i, origMethodName.s, newMethodName.s, newMethodFunc.i)
Protected.i origSel, newSel
Protected.i origMethodImp, origTypeEnc
Protected.i origMethod, newMethod
Protected.s origTypeEncStr
origSel = sel_registerName_(origMethodName)
newSel = sel_registerName_(newMethodName)
;Replace only if the new method does not exists.
If class_getInstanceMethod_(class, newSel) = 0
origMethod = class_getInstanceMethod_(class, origSel)
origMethodImp = method_getImplementation_(origMethod)
;Get original method type encoding
origTypeEnc = method_getTypeEncoding_(origMethod)
If origTypeEnc
origTypeEncStr = PeekS(origTypeEnc, -1, #PB_UTF8)
EndIf
;Add new method without implementation
class_addMethod_(class, newSel, 0, origTypeEncStr)
newMethod = class_getInstanceMethod_(class, newSel)
;Replace original method with new method implementation (newMethodFunc)
class_replaceMethod_(class, origSel, newMethodFunc, origTypeEncStr)
;Set the new method implementation with the original method implementation.
If origMethodImp
method_setImplementation_(newMethod, origMethodImp)
EndIf
EndIf
ProcedureReturn origMethodImp
EndProcedure
ProcedureC my_on_dealloc(self.i, cmd.i)
Debug "my_on_dealloc"
;do something
;Call the original method, since it has been switched my_dealloc holds the
;original implementation thus not entering in recursion.
CocoaMessage(0, self, "my_dealloc")
EndProcedure
ProcedureC my_on_viewDidHide(self.i, cmd.i)
Debug "my_on_viewDidHide"
;do something
;Call original method
CocoaMessage(0, self, "my_viewDidHide")
EndProcedure
Procedure main()
Protected.i win, btn1, btn2, ev, btnClass
win = OpenWindow(#PB_Any, 10, 10, 400, 300, "Test")
btn1 = ButtonGadget(#PB_Any, 10, 10, 80, 30, "Hide")
btn2 = ButtonGadget(#PB_Any, 10, 50, 80, 30, "Free")
btnClass = object_getClass_(GadgetID(btn1))
cocoa_swizzle_methods(btnClass, "dealloc", "my_dealloc", @my_on_dealloc())
cocoa_swizzle_methods(btnClass, "viewDidHide", "my_viewDidHide", @my_on_viewDidHide())
Repeat
ev = WaitWindowEvent()
Select ev
Case #PB_Event_Gadget
Select EventGadget()
Case btn1
HideGadget(btn1, #True)
Case btn2
FreeGadget(btn2)
EndSelect
EndSelect
Until ev = #PB_Event_CloseWindow
EndProcedure
main()