Reputation: 6103
I am trying to catch all touch events globally. For that I know I can hook the touch event procedures inside the UIView class. I have the code that compiles. My implementation of the hook is
procedure touchesBeganDetour(self: id; _cmd: SEL; touches: NSSet; withEvent: UIEvent); cdecl;
begin
Sleep(1);
end;
And then I tried to hook it two different ways. First:
constructor TTouchEventListener_IOS.Create;
var
FM1, FM2: Pointer
ViewClass: Pointer;
begin
inherited;
ViewClass := objc_getClass('UIView');
class_addMethod(ViewClass, sel_getUid('touchesBeganDetour:'), @touchesBeganDetour, 'v@:@@');
FM1 := class_getInstanceMethod(ViewClass, sel_getUid('touchesBegan:withEvent:'));
FM2 := class_getInstanceMethod(ViewClass, sel_getUid('touchesBeganDetour:'));
method_exchangeImplementations(FM1, FM2);
end;
This seems to be the standard approach. And the second one:
constructor TTouchEventListener_IOS.Create;
var
FM1
ViewClass: Pointer;
begin
inherited;
ViewClass := objc_getClass('UIView');
FM1 := class_getInstanceMethod(ViewClass, sel_getUid('touchesBegan:withEvent:'));
method_setImplementation(FM1, @touchesBeganDetour);
end;
This should also work as far as I understand. I get the instance of "touchesBegan:withEvent" and all the code executes without errors. But when I then touch the simulator screen the code crashes inside "DispatchToImportSuper" in unit "Macapi.ObjectiveC.pas". I am obviously doing something wrong but I have no clue what. If this works it would make possible to listen to touch events without modifying the Delphi source code.
Anyone has any ideas?
Upvotes: 3
Views: 627
Reputation: 6103
To again answer my own question. The problem was in the detour procedure declaration. It seems you cannot have the original parameters specified, but you have to use pointers instead of interfaces. This is probably due to differences between objectiveC and object pascal. You later "wrap" and thus cast the pointers to correct interfaces.
procedure touchesBeganDetour(self: id; _cmd: SEL; touches: Pointer; withEvent: Pointer); cdecl;
begin
DoNotifyTouchEvent(TNSSet.Wrap(touches), TUIEvent.Wrap(withEvent), teDown);
end;
Upvotes: 2