Прикосновение к крючку начинается в классе UIView [Swizzling] с Delphi XE5

Я пытаюсь поймать все сенсорные события во всем мире. Для этого я знаю, что могу подключить процедуры сенсорного события внутри класса UIView. У меня есть код, который компилируется. Моя реализация крючка

procedure touchesBeganDetour(self: id; _cmd: SEL; touches: NSSet; withEvent: UIEvent); cdecl;
begin
  Sleep(1);
end;

И тогда я попытался подключить его двумя разными способами. Первый:

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;

Это кажется стандартным подходом. И второй:

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;

Это также должно работать, насколько я понимаю. Я получаю экземпляр "touchesBegan: withEvent", и весь код выполняется без ошибок. Но когда я прикасаюсь к экрану симулятора, код падает внутри "DispatchToImportSuper" в блоке "Macapi.ObjectiveC.pas". Я явно делаю что-то не так, но понятия не имею, что. Если это сработает, это позволит прослушивать сенсорные события без изменения исходного кода Delphi.

У кого-нибудь есть идеи?

1 ответ

Решение

Чтобы снова ответить на мой собственный вопрос. Проблема была в декларации процедуры объезда. Кажется, вы не можете указать исходные параметры, но вы должны использовать указатели вместо интерфейсов. Вероятно, это связано с различиями в ObjectiveC и Паскале объекта. Позже вы "обернетесь" и таким образом приведете указатели к правильным интерфейсам.

procedure touchesBeganDetour(self: id; _cmd: SEL; touches: Pointer; withEvent: Pointer); cdecl;
begin
  DoNotifyTouchEvent(TNSSet.Wrap(touches), TUIEvent.Wrap(withEvent), teDown);
end;
Другие вопросы по тегам