سؤال

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?

هل كانت مفيدة؟

المحلول

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;
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top