简体   繁体   English

使用Delphi XE5在UIView类[Swizzling]中使用Hook touchesBegan

[英]Hook touchesBegan inside UIView class [Swizzling] with Delphi XE5

I am trying to catch all touch events globally. 我试图在全球范围内捕捉所有触摸事件。 For that I know I can hook the touch event procedures inside the UIView class. 为此,我知道我可以在UIView类中挂钩触摸事件过程。 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. 我得到了“ touchesBegan:withEvent ”的实例,并且所有代码都执行没有错误。 But when I then touch the simulator screen the code crashes inside " DispatchToImportSuper " in unit " Macapi.ObjectiveC.pas ". 但是当我接触模拟器屏幕时,代码在单元“ Macapi.ObjectiveC.pas ”中的“ DispatchToImportSuper ”内崩溃。 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. 如果这样可行,则可以在不修改Delphi源代码的情况下收听触摸事件。

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. 这可能是由于objectiveC和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 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM